【问题标题】:Hunting for “too many files” cause寻找“太多文件”的原因
【发布时间】:2010-11-16 11:35:46
【问题描述】:

我们在一个客户服务器上遇到了一个奇怪的问题,Java 遇到“文件过多”,

通过 lsof 检查描述符会产生大量带有“无法识别协议”的“sock”描述符。

我怀疑这是由于套接字打开时间过长造成的,但由于我们的线程转储包含很多套接字,我不清楚到底是谁造成的。

有什么好的方法可以检测哪些线程准确打开了这些套接字?

谢谢。

【问题讨论】:

    标签: java linux sockets


    【解决方案1】:

    有什么好的方法可以检测哪些线程确实打开了这些套接字?

    不是线程本身

    一种方法是使用分析器运行应用程序。即使您不能准确地重现客户的问题,这也可以很好地找到问题。 (@SyBer 报告说 YourKit 分析器具有特定支持以查找套接字泄漏...请参阅评论。)

    第二种方法是使用ulimit 调整您的测试平台,以减少允许的打开文件数。这可能更容易在您的测试环境中重现“打开的文件过多”的情况。

    最后,我建议“grepping”您的代码库以查找创建套接字对象的所有位置。然后检查它们以确保它们正确使用 try / finally 块以确保套接字始终关闭。

    【讨论】:

    • "一种方法是使用分析器运行应用程序。即使您不能准确地重现客户的问题,这也可以很好地发现问题。"探查器能否捕捉到此类问题?
    • 适当使用分析器可以检测到资源(例如套接字)泄漏的存在,否则可能不会被注意到。
    • 我们发现YourKit profiler内置了sockets监控,这对寻找打开的sockets很有帮助,最终解决了我们所有的描述符泄露问题。
    • @SyBer 除了YourKit,还有其他免费选项吗?
    【解决方案2】:

    开始

    netstat -ano | grep $YOUR_PROCESS_ID - 适用于 unix

    netstat -ano | find "$YOUR_PROCESS_ID" - 适用于窗户

    至少你会看到连接是否真的存在。

    【讨论】:

    • 在 Ubununtu 上,您可能需要将 --program 选项传递给 netstat 以输出进程 ID(即 PID)。
    【解决方案3】:

    您是否尝试ulimit 来增加打开文件的数量?此外,您可能没有正确关闭套接字,因此您有泄漏。

    【讨论】:

    • 我可以做到,但这确实是一个临时解决方案,直到它再次增长。我们试图关闭套接字,但似乎确实有一个被遗忘的。
    【解决方案4】:

    检测泄漏套接字的唯一“好”方法是非常详细的日志或分析器。执行内存转储并分析对象。

    【讨论】:

      【解决方案5】:

      Valgrind 将在您传递--track-fds=yes 时识别文件描述符泄漏。 Valgrind 在其跟踪的资源的“获取”点生成短堆栈跟踪。当您找到发生泄漏的源行后,您可以将其与 pthread_self 的返回值结合到您的日志系统(我确定您会使用一个!),或者放置breakpoints 在 gdb 中。

      您可能忽略了已完成的close() 套接字。即使对等方启动关闭,也需要执行此操作。

      【讨论】:

      • Valgrind 适用于 C / C++,不适用于 Java。
      • “天地之间还有更多的东西,霍雷肖”:)。无论如何,谢谢。
      • javalinux 标签一起使用没有错。
      猜你喜欢
      • 1970-01-01
      • 2011-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多