Linux宿主机下/容器下如何修改进程打开的文件句柄数(open files)
作者:Leon_start
系统级的max-file和进程级的ulimit-n分别控制文件句柄的最大数量,系统级限制整个系统,而ulimit-n只限制单个进程,当进程打开的文件句柄数超限时,会报“Too many files open”错误,可以通过特定命令查看和修改这些值
Linux宿主机下/容器下修改进程打开的文件句柄数
背景1:平台调用算法出现异常,查看数据库调用错误状态码是499
- 499:(客户端主动关闭请求);客户端向服务端发起请求,服务器端处理的时间过长,超出了客户端的超时时间,客户端主动断开连接。
- ## 这个报错表明请求已经打到了后端算法,只是后端算法请求太多导致的,迟迟没有响应客户端并返回结果而导致断开连接,此时可以增加服务后端节点数分摊压力或者增加文件句柄数(增加文件句柄数可以让算法接收更多的请求)
背景2:错误日志出现“Too many open files“等文件打开太多等错误,出现文件描述符耗尽的问题
背景3:容器里面的服务启动异常,排查发现容器里面文件句柄数太少,大概率是容器本身配置的句柄数过低
max-file
表示系统级别的能够打开的文件句柄的数量。是对整个系统的限制,并不是针对用户的。ulimit -n
控制进程级别能够打开的文件句柄的数量。提供对shell及其启动的进程的可用文件句柄的控制,这是进程级别的
对于服务器,一般修改进程级的最大打开文件句柄数即可(系统默认1024,有点小)。一般不需要调整系统级的最大数。
如果出现了达到系统级别最大限制时,也需要同步调整系统级的最大数的。
一、查看系统最大句柄数
Linux 中,单个进程能够打开的最大文件句柄数量是可以配置的,系统默认是 1024。
当单个进程打开的文件句柄数量超过了系统定义的值,就会出现“Too many files open”的错误提示。
用户可以通过以下命令查看系统定义的最大值:
#查看文件句柄 [root@localhost ~]# ulimit -a #查看当前进程打开了多少句柄数: [root@localhost ~]# lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr|more 131 24204 57 24244 57 24231 ...... 其中第一列是打开的句柄数,第二列是进程ID。可以根据ID号来查看进程名: [root@localhost ~]# ps aef|grep 24204 nginx 24204 24162 99 16:15 ? 00:24:25 /usr/local/nginx/sbin/nginx -s
二、修改文件句柄(进程级别)
#对于一般的应用程序而言 1024 已经完全够用了,但是有些进程处理大量请求,很有可能 1024 就不够用了,则需要调整系统参数,一般可以设置4096、65535或者102400,设置的太高会影响性能,并不是想设置多高就多高,毕竟打开的文件句柄数越多响应时间肯定会越慢
#临时生效 [root@localhost ~]# ulimit -n 4096 #永久生效法一:把这个临时生效的命令放在.bashrc或者.bash_profile配置文件里就可以永久生效了 [root@localhost ~]# echo "ulimit -n 4096" >> ~/.bashrc #永久生效法二 [root@localhost ~]# vim /etc/security/limits.conf * soft nofile 65535 * hard nofile 65535 提示:* 表示所用的用户,但有的系统不认, 需要具体的用户名, 比如: root soft nofile 65535 root hard nofile 65535 重新登录验证,或reboot后验证。
三、修改max user processes进程数
#临时生效 [root@localhost ~]# ulimit -u 65536 #永久生效 [root@localhost ~]# vim /etc/security/limits.conf * soft nproc 65536 * hard nproc 65536
四、查看系统最大打开文件描述符数量(系统级别)
[root@localhost ~]# cat /proc/sys/fs/file-max #查看系统最大打开文件描述符数量 180965 [root@localhost ~]# echo "1000000" > /proc/sys/fs/file-max #临时设置该值 #永久性设置,需要在/etc/sysctl.conf中设置,并让它生效: [root@localhost ~]# echo "fs.file-max = 1000000" >> /etc/sysctl.conf [root@localhost ~]# sysctl -p fs.file-max = 1000000
注意:
- 所有进程打开的文件描述符数量不能超过/proc/sys/fs/file-max。
- 单个进程打开的文件描述符数不能超过user limit中nofile的soft limit。
- nofile的soft limit不能超过其hard limit。
五、容器内部修改文件句柄
##这是针对已经run起来的容器修改文件句柄 [root@localhost ~]# ps -ef | grep dockerd root 57213 1 0 Jan13 ? 02:49:32 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --icc=false --default-ulimit nproc=1024:2408 --default-ulimit nofile=100:200 root 126923 122986 0 10:44 pts/2 00:00:00 grep --color=auto dockerd [root@localhost ~]# cat /usr/lib/systemd/system/docker.service #把宿主机本身容器配置文件这一条修改后重启就会生效 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --icc=false --default-ulimit nproc=1024:2408 --default-ulimit nofile=65535:131070 [root@localhost ~]# systemctl restart docker && systemctl daemon-reload
--default-ulimit nofile=100:200,也就是文件句柄容器内100,宿主机200
#没有run运行起来的容器,可以直接在容器启动命令添加限制参数: --ulimit nofile=65535:65535,容器启动完成后,在容器内查看java进程句柄数限制(已经成功修改为65535) [root@localhost ~]# docker run --ulimit nofile=65535:65535 ...
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。