查找哪个线程导致打开文件过多问题以及为什么在 lsof 输出中出现重复的节点 ID

Find which thread is causing too many open files issue and why duplicate node ids in lsof output

我们的 java 应用程序在 运行 之后长时间抛出 "Too many open files" 问题。 调试问题后,可以看到根据 lsof 输出打开了很多 fds。

# lsof -p pid | grep "pipe" | wc -l

698962

# lsof -p pid | grep "anon_inode" | wc -l

349481

------------少量lsof数据----------

COMMAND   PID  USER   FD  TYPE             DEVICE SIZE/OFF       NODE NAME
java    23994  app 464u  0000                0,9        0       3042 anon_inode
java    23994  app 465u  0000                0,9        0       3042 anon_inode
java    23994  app 466r  FIFO                0,8      0t0  962495977 pipe
java    23994  app 467w  FIFO                0,8      0t0  962495977 pipe
java    23994  app 468r  FIFO                0,8      0t0  963589016 pipe
java    23994  app 469w  FIFO                0,8      0t0  963589016 pipe
java    23994  app 470u  0000                0,9        0       3042 anon_inode
java    23994  app 471u  0000                0,9        0       3042 anon_inode

如何找出许多打开 FIFO 和 0000 类型 FD 的根本原因。 我们的应用程序中没有很多文件 read/writes。使用内部使用 Nio 的 apache mina 框架从流中读取了如此多的 TCP 消息。

这些是我的问题

  1. 我们检查了 /proc/pid/task/ 文件夹。有很多文件夹。它是否对应于线程 ID?但是根据 jstack,有 141 个线程,因为这个文件夹有 209 个子文件夹。
  2. 如何找到导致 fd 泄漏的线程?在我们的例子中,任务文件夹中的大部分文件夹对应于许多 fds。 IE。 /proc/pid/task/threadid/fd文件夹有很多fd记录
  3. lsof
  4. 中pipe和anon_inodes的可能原因是什么
  5. FD类型0000是什么意思
  6. 所有 anon_inode 都具有相同的节点 ID 3042。这是什么意思?

最有可能的是您正在打开资源,然后没有正确关闭它们。确保使用适当的方法(例如 try-with-resources 或 try-finally 块)进行整理。

要找到问题,您应该通过 class 路由所有 IO,然后跟踪打开和关闭,甚至可能记住堆栈跟踪。然后您可以查询它并查看您在哪里泄漏资源。

我们发现了问题。有一个代码流创建了 org.apache.mina.transport.socket.nio.NioSocketConnector,但在某些情况下没有关闭。为了找到问题,我们做了以下

  1. 我们在 linux 服务器中启用了 strace
  2. 我们为这个过程做了几分钟的 strace
  3. 我们可以确定导致问题的线程 ID
  4. 我们从 jstack 中找到线程 class。