由lsof发现,但不是由netstat发现的套接字

我有一个应用程序正在耗尽文件描述符,显然是通过打开套接字,但我无法确切地知道这些套接字是做什么的。 这些出现在lsof输出中

java 9689 appuser 1010u sock 0,5 263746675 can't identify protocol java 9689 appuser 1011u sock 0,5 263746676 can't identify protocol java 9689 appuser 1012u sock 0,5 263746677 can't identify protocol java 9689 appuser 1014u sock 0,5 263746678 can't identify protocol java 9689 appuser 1015u sock 0,5 263746679 can't identify protocol java 9689 appuser 1016u sock 0,5 263746681 can't identify protocol 

并在/ proc / $ PID / fd中为

 lrwx------ 1 appuser appuser 64 Jun 23 11:49 990 -> socket:[263732085] lrwx------ 1 appuser appuser 64 Jun 23 11:49 991 -> socket:[263732086] lrwx------ 1 appuser appuser 64 Jun 23 11:49 992 -> socket:[263735307] lrwx------ 1 appuser appuser 64 Jun 23 11:49 993 -> socket:[263732088] lrwx------ 1 appuser appuser 64 Jun 23 11:49 995 -> socket:[263735308] lrwx------ 1 appuser appuser 64 Jun 23 11:49 996 -> socket:[263735309] lrwx------ 1 appuser appuser 64 Jun 23 11:49 997 -> socket:[263745434] lrwx------ 1 appuser appuser 64 Jun 23 11:49 998 -> socket:[263745435] lrwx------ 1 appuser appuser 64 Jun 23 11:49 999 -> socket:[263745436] 

netstat -a没有类似的输出。

这些sockets是什么,我怎么知道他们做了什么?

编辑 :我已经尝试运行grep $SOCKET /proc/net ,如在lsof常见问题 ,其中$ SOCKET是例如263746679build议,但也没有给出任何结果。


作为背景,该应用程序是一个多任务的容器,其中包括执行networking调用。 我需要挑出一个狂暴的人,但是直到我发现这些套接字与谁沟通,我都被卡住了。

    如果您创build一个套接字,可能会发生这种情况,但从来没有连接()或绑定()。 你最好的办法可能是对应用程序进行strace(-fF),然后与lsof的输出进行交叉引用,以确定哪个套接字引发了这个问题。 作为一种额外的debugging方法:如果你使用debugging信息来封装你的套接字调用,并把它们写到/ dev / null中,它会以strace的forms出现,而不会给你带来欢乐的大日志文件。

    我要做的第一件事是如果你的文件描述符限制,

     ~# vi /etc/sysctl.conf fs.file-max = 331287 

    接下来,我将确保您的系统是最新的,这包括所有库和服务器。 它可能是您的Java应用程序服务器已过期(如果您正在使用)。 它也可能是你的应用程序服务器configuration错误,你应该看看你的configuration文件,并降低你的connectionTimeout和/或你的maxKeepAliveRequests (我不知道你使用的应用程序服务器,或者如果你使用一个…) 。

    我不确定这个应用程序是干什么的,但是如果你不认为它需要数以万计的套接字,那么这几乎肯定是你的Java应用程序中的“文件描述符泄漏” 。 您可能需要向供应商发送错误报告。 在这个错误报告中,您应该包含有关如何重新创build问题的信息。

    以下是一些debugging问题的方法。

    Wireshark(或用于cli的twireshark)是了解如何使用这些套接字的最佳工具。 Wireshark会给你一个通过电线抛出的交通types的细分。 它有可能是前几个连接将成功,然后将达到文件描述符限制。 一旦文件描述符限制被命中,那么Wireshark将不会接pipe任何东西(整数就是netstat),但这将有助于缩小问题的范围。 也许有很多传出的SYN被发送的情况,但是没有收到SYN / ACK,因此大量的TCP连接只是处于SYN_WAIT状态。

    如果你有权访问源代码,并且知道正在创build的套接字的types(比如使用strace或只是search代码),那么你可以在Eclipse(或其他IDE)中打开该项目,并设置一个中断点正在创build这些套接字。 当断点被击中时,您可以查看堆栈跟踪。 这个文件描述符泄漏可能是一个简单的无限循环,或者套接字超时值可能太大。 另一种可能性是java应用程序没有执行socket.close()来清理连接。 做一个closures通常是在一个try/catchfinely块中完成的(是的,套接字必须总是有一个try / catch在Java中,否则不会build立:)。 在一天结束时,Java应用程序可能没有正确处理它的IOException。

    使用Python,我在SSL套接字上遇到了同样的问题:

    • 当我使用socket.close()时,套接字将处于CLOSE_WAIT状态无限期
    • 当我使用socket.shutdown()时,lsof说“不能识别协议”

    解决scheme是在closures之前打开SSL层:

    • origsock = socket.unwrap()
    • origsock.close()

    这在我的应用程序中正确closures了套接字。