关于文件句柄数和线程数,这两篇文章讲的不错:
https://www.cnblogs.com/sxdcgaq8080/p/11136887.html
https://www.cnblogs.com/sxdcgaq8080/p/11136952.html
最近测试同事在做压力测试的时候,Linux上的Java程序报异常:Too many open files
Linux一切都是文件,而文件句柄限制,就是规定的单个进程能够打开的最大文件句柄数量(Socket连接也算在里面)
Linux的 limit 限制分为2个策略:软限制和硬限制,硬限制就是实际的限制,而软限制是警告限制,它只会给出警告。
通过ulimit -a 可以查看当前所有的limit信息,-S 是软限制,-H是硬限制,默认是软限制:
查看 limit 软限制(等同于 ulimit -Sa):
[root@ylserver106860142 ~]# ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 79571 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 79571 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
查看 limit 硬限制:
[root@ylserver106860142 ~]# ulimit -Ha core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 79571 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 4096 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) unlimited cpu time (seconds, -t) unlimited max user processes (-u) 79571 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
文件句柄
通过 ulimit -Hn 命令可以看到默认每个进程的文件句柄硬限制为4096,其实通过 /proc/PID 目录也可以查到到进程相关信息
先查看进程的PID号:
[root@ylserver106860142 ~]# ps aux|grep -v grep |grep demo.jar root 20506 16.6 10.1 11322224 2059868 pts/1 Sl 14:03 49:00 /usr/local/java/jdk1.8.0_111/jre/bin/java -jar demo.jar [root@ylserver106860142 ~]#
通过PID号查看进程的 limit 信息,默认文件句柄硬限制为4096:
[root@ylserver106860142 ~]# cat /proc/20506/limits Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 0 unlimited bytes Max resident set unlimited unlimited bytes Max processes 79571 79571 processes Max open files 4096 4096 files Max locked memory 65536 65536 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 79571 79571 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited us
查看进程持有的句柄数,上面的 Too many open files 原因也就是由此而来:
[root@ylserver106860142 ~]# ls /proc/20506/fd/|wc -l 4096 [root@ylserver106860142 ~]#
永久修改文件句柄限制:
[root@ylserver106860142 ~]# cat /etc/security/limits.conf |egrep -v "#|^$" * soft nofile 655350 * hard nofile 655350 [root@ylserver106860142 ~]#
重开一个终端,查看是否生效:
[root@ylserver106860142 ~]# ulimit -Hn 655350 [root@ylserver106860142 ~]#
将程序重启后,查看进程 文件句柄限制信息:
[root@ylserver106860142 ~]# cat /proc/19091/limits |grep "open" Max open files 655350 655350 files [root@ylserver106860142 ~]#
查看进程持有的文件句柄数,可以看到已经超过4096:
[root@ylserver106860142 ~]# ls /proc/19091/fd/|wc -l 4493 [root@ylserver106860142 ~]#
如果是systemd service服务,则需要在对应的service文件添加 LimitNOFILE=655350
系统级文件限制
上面讲的都是基于单个进程的文件句柄限制,查看Linux系统最大的文件句柄限制:
[root@ylserver106860142 ~]# cat /proc/sys/fs/file-max 2016339 [root@ylserver106860142 ~]#
修改最大文件句柄限制:
[root@ylserver106860142 ~]# echo "fs.file-max = 6553560" >> /etc/sysctl.conf [root@ylserver106860142 ~]# sysctl -p fs.file-max = 6553560 [root@ylserver106860142 ~]#
验证一下:
[root@ylserver106860142 ~]# cat /proc/sys/fs/file-max 6553560 [root@ylserver106860142 ~]#
进程数限制
跟文件句柄一样,每个用户都有进程数限制,在Linux下运行多线程时,每个线程的实现其实是一个轻量级的进程,对应的术语是: light weight process(LWP)
配置每个用户进程数上限(nproc):
[root@ylserver106860142 ~]# cat /etc/security/limits.d/20-nproc.conf |grep -v "#" * soft nproc 204800 * hard nproc 204800
重新开一个终端,验证一下:
[root@ylserver106860142 ~]# ulimit -u 204800
如果是systemd service服务,则需要在对应的service文件添加 LimitNPROC=204800
线程数
使用ps 命令是加上 -L 参数可以查看线程数,在 进程的 /proc/PID/task/ 目录下也可以查看线程数
查看 PID 为 6250 的线程数:
[root@ylserver106860142 ~]# ps -eLf|grep 6250|grep -v grep |wc -l 105 [root@ylserver106860142 ~]# ls /proc/6250/task/|wc -l 105
查看 root 用户的 线程总数(effective user):
[root@ylserver106860142 ~]# ps -u root -Lf|wc -l 1927
查看 root 用户的 线程总数(real user):
[root@ylserver106860142 ~]# ps -U root -Lf|wc -l 1928
这里要注意一下,进程创建的时候存在real user和effective user两个属性,ps命令统计的时候默认显示的是effective user的进程数,nproc限制值是限制的real user创建的进程线程数
-u 参数查看的是 effective user, 使用 -U 参数查看的是 real user