进程耗尽打开的文件句柄

进程耗尽打开的文件句柄

我的应用程序基于两个通过 http 连接交换数据的 Java 进程,运行文件并产生以下错误消息:

Aug 14 11:27:40 server sender[8301]: java.io.IOException: Too many open files
Aug 14 11:27:40 server sender[8301]: at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
Aug 14 11:27:40 server sender[8301]: at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
Aug 14 11:27:40 server sender[8301]: at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
Aug 14 11:27:40 server sender[8301]: at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:455)
Aug 14 11:27:40 server sender[8301]: at java.lang.Thread.run(Thread.java:748)

这两个进程都在 SystemD 的控制之下。我使用检查了进程cat /proc/5882/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             63434                63434                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       63434                63434                signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us

当我运行时,lsof | grep pid | wc -l我的条目少于 2000 个(我以这种方式运行 lsof 因为从尝试获取每个进程打开文件的计数时与 lsof 命令存在差异

我完全不知道我可以进一步检查或增加什么。

答案1

判断进程有多少个打开的文件描述符的最佳方法是使用:

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

(假设 PID 8301,就像您的日志中一样。)

运行lsof将遍历整个/proc树,并尝试解析所有文件的名称(这些是伪符号链接,需要调用每个文件的 readlink 进行解析),因此运行lsof将花费很长时间(取决于您的计算机的繁忙程度),所以当你看到结果时,可能一切都已经改变了。使用起来ls /proc/${pid}/fd/会很快(只需一次 readdir 调用),因此更有可能捕获接近当前情况的内容。

关于解决问题,您可能需要考虑增加服务允许的文件描述符的数量,您可以通过设置 LimitNOFILE=指令在你的 systemd 单元文件中。

相关内容