Too many open files异常问题的排查

  其他常见问题
内容纲要

概要描述


在linux系统中遵循一切都是文件的原则,即磁盘文件、目录、网络套接字、磁盘、管道等,都是文件,在我们进行打开的时候会返回一个fd,即是文件句柄。如果频繁的打开文件,或者打开网络套接字而忘记释放就会有句柄泄露的现象。
linux系统中对进程可以调用的文件句柄数进行了限制,如果超过了限制,进程将无法获取新的句柄,而从导致不能打开新的文件,报错too many open files,即句柄数超出系统限制。这里的files不单是文件的意思,也包括打开的通讯链接(比如socket),正在监听的端口等。

详细说明


本文主要从两方面排查,一是系统配置,二是应用层面。

系统配置

根据应用权限,又分为系统级和用户级。系统级的修改会对所有用户有效,而用户级只限制每个登录用户的可连接文件数。

修改用户级别限制

通过命令ulimit -a查看当前系统设置的最大句柄数是多少,open files那一行就代表系统目前允许单个进程打开的最大句柄数,这里是327680。
TDH集群默认是327680,普通情况下linux默认是1024。
file

然后,查看下当前进程占用句柄的情况:

查看全部进程占用句柄数总和:

lsof | awk '{print $2}' | wc -l

补充

查看某一个进程占用句柄数:

ls -l /proc//fd | wc -l

查看系统中进程打开文件数的排序:

lsof -n | awk '{print $2}' | sort | uniq -c | sort -nr | more

如果句柄数占用过多,则可以修改最大句柄数限制,如:
设置最大句柄数为102400

ulimit -SHn 102400

-H:设置硬件资源限制;
-S:设置软件资源限制;
-n size:设置内核可以同时打开的文件描述符的最大值,可以设置的最大值为655350。

这种方式设置后在重启后会还原为默认值。
如果要永久生效,需要修改系统配置文件/etc/security/limits.conf

vim /etc/security/limits.conf
#在最后添加
* soft nofile 102400
* hard nofile 102400

第一列为用户名,*表示所有用户。
hard的设置是实际的默认值,也就是上限;
soft的配置只是用来警告的,如果超过了soft的值,会有warn;

或者只添加

* - nofile 102400

(hard和soft同时配置的方式,是最简单的全局设置。)

修改系统级别限制

上述的ulimit是对进程的限制,对系统总的限制需要设置file-max,可以通过命令来查看fs.file-max的配置:

cat /proc/sys/fs/file-max
或者
sysctl -a
cat /proc/sys/fs/file-max

表示当前内核可以打开的最大的文件句柄数,一般为内存大小(KB)的10%,一般我们不需要主动设置这个值,除非这个值确实较小。

cat /proc/sys/fs/file-nr
12640   0       727680

第一个数字表示当前系统打开的文件数。第三个数字和cat /proc/sys/fs/file-max结果一样表示当前内核可以打开的最大的文件句柄数。

设置的可以分为临时改动和永久改动,临时改动直接可用sysctl -w [变量名]=[值]来解决。例如:

synctl -w fs.file-max=102400

永久改动就需要修改/etc/sysctl.conf文件,如果文件中没有fs.file-max属性,则添加。
设置完成后,使用sysctl -p来加载系统参数,在不指定文件位置的情况下,默认会从/etc/sysctl.conf文件中加载。

应用层面

应用层面一般最常见的原因是连接的泄漏(未正确关闭)导致。

排查过程:

查看close_wait连接数量

netstat -anp | grep CLOSE_WAIT | wc -l

查看具体PID的连接数量(单个节点组件也不会太多,可以逐一排查)

netstat -anp | grep  | wc -l

定位到某一个具体的进程后,可以grep 端口,定位泄漏连接的另一端

netstat -anp | grep 

例如发现kafka的jmx 9999 端口存在大量的close_wait

netstat -anp | grep 9999

输出如下

tcp6       0      0 :::9999                 :::*                    LISTEN      16030/java
tcp6       0      0 172.16.2.27:9999        172.16.2.27:47155       ESTABLISHED 16030/java
tcp6       0      0 172.16.2.27:47155       172.16.2.27:9999        ESTABLISHED 1147/java

则可判断1147为连接的另一端进程。

ps -ef | grep 1147

输出

root      1147     1  1 8月31 ?       07:24:24 /usr/java/latest/bin/java -agentpath:/usr/lib/transwarp-manager/agent/lib/native/libagent.so -Xms512m -Xmx1024m -XX:MaxPermSize=128m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/transwarp-manager/agent/agent_gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/transwarp-manager/agent -Dfile.encoding=UTF-8 -Dtranswarp.root.logger=INFO, R -Djava.io.tmpdir=/tmp -Djava.library.path=/usr/lib/transwarp-manager/agent/lib/native -Dsun.net.client.defaultConnectTimeout=5000 -Dsun.net.client.defaultReadTimeout=5000 -Dsun.rmi.transport.tcp.handshakeTimeout=10000 -Dsun.rmi.transport.tcp.responseTimeout=15000 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=48121 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -cp /etc/transwarp-manager/agent:/usr/lib/transwarp-manager/agent/lib/*:/usr/lib/transwarp-manager/agent/../common/lib/* io.transwarp.manager.agent.application.TranswarpAgent
root      5101  8751  0 12:27 pts/0    00:00:00 grep --color=auto 1147

得到结论 manager进程到请求kafka的9999 jmx监控端口可能未正确释放,存在问题。

如果netstat查看一切正常,那么可以查看proc目录下具体PID下fd文件数量.(此处的数量过大的进程,同样是异常的)

 ls /proc//fd | wc -l

优先定位到具体的组件进程,然后再进一步结合组件日志分析原因。

这篇文章对您有帮助吗?

平均评分 0 / 5. 次数: 0

尚无评价,您可以第一个评哦!

非常抱歉,这篇文章对您没有帮助.

烦请您告诉我们您的建议与意见,以便我们改进,谢谢您。