【问题标题】:Linux - "Too many open files" with pipe, how to debugLinux - 带有管道的“打开的文件太多”,如何调试
【发布时间】:2014-06-16 01:27:08
【问题描述】:

我有一个 Java 程序,运行大约 3 分钟后会抛出“打开的文件太多”错误。增加打开文件限制不起作用,因为它仍然会用完所有限制,只是速度较慢。所以我的程序有问题,我需要找出来。

这是我所做的,10970 是 pid

  • 使用cat /proc/10970/fd检查Java进程打开的文件,发现大部分是管道
  • 使用lsof -p 10970 | grep FIFO 列出所有管道并找到大约 450 个管道
  • 管道如下所示

java 10970 服务 1w FIFO 0,8 0t0 5890 管道

java 10970 服务 2w FIFO 0,8 0t0 5890 管道

java 10970 服务 169r FIFO 0,8 0t0 2450696 管道

java 10970 服务 201r FIFO 0,8 0t0 2450708 管道

但我不知道如何继续。上面输出中的0,8 表示设备号。如何找到具有这些编号的设备?

更新

该程序是一个 TCP 服务器,从客户端接收套接字连接并处理消息。我有两个环境。在生产环境中它工作正常,但在测试环境中它最近有这个问题。在生产环境中,我看不到这么多管道。这两个环境的代码和基础架构相同,均由 Chef 管理。

【问题讨论】:

  • 这个问题很模糊。你的程序是做什么的?另外,您是否会关闭“连接”?

标签: java linux ubuntu pipe


【解决方案1】:

但我不知道如何继续。

您需要做的是确定您在 Java 代码中打开这些管道的一个或多个位置……并确保在完成这些管道后它们始终处于关闭状态。

确保管道已关闭的最佳方法是在使用完管道后显式关闭它们。例如(使用输入流而不是套接字...):

    InputStream is = new FileInputStream("somefile.txt");
    try {
         // Use file
    } finally {
         is.close();
    }

在 Java 7 或更高版本中,您可以更简洁地写成 ///

    try (InputStream is = new FileInputStream("somefile.txt")) {
         // Use file
    }

在后者中,InputStream object 会在 try 在隐式 finally 块中完成时自动关闭。


上面输出中的 0,8 表示设备号。如何找到具有这些编号的设备?

这可能与解决问题无关。关注为什么文件描述符没有被关闭。知道设备编号的含义并没有帮助。

在生产环境中我看不到这么多管道。

这可能也是一个红鲱鱼。这可能是由于 GC 运行更频繁,并且在成为问题之前关闭了孤立的文件描述符。

(但是强制GC运行不是解决办法,你不应该依赖GC来关闭文件描述符。它效率低且不可靠。)

【讨论】:

  • 我如何知道哪些 java 方法创建了 linux 管道?
猜你喜欢
  • 2021-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多