我目前正在与一些糟糕的(定制)服务器软件作斗争,它不能正确接受连接(由一个从未接触过套接字更不用说线程的 PHP 程序员用 Java 编写)。我猜想在客户端线程中正确接受套接字之前线程正在死亡。我不能确定,而且这实际上并不重要,因为该软件目前正在重新实现;旧版本必须保持运行,直到新版本上线,尽可能可靠,但不需要花费任何时间和金钱来调试旧代码库。
这个错误表现在以下 netstat 输出中;一些连接从未从内核转移到使用空间(这是我的解释,欢迎提出更好的解释):
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp6 228 0 192.0.2.105:1988 46.23.248.10:7925 ESTABLISHED -
tcp6 0 0 192.0.2.105:1988 221.130.33.37:9826 ESTABLISHED 14741/java
tcp6 0 0 192.0.2.105:1988 46.23.248.2:5867 ESTABLISHED 14741/java
tcp6 2677 0 192.0.2.105:1988 221.130.33.37:15688 ESTABLISHED -
tcp6 3375 0 192.0.2.105:1988 221.130.33.36:3045 ESTABLISHED -
tcp6 14742 0 192.0.2.105:1988 46.23.248.17:4679 ESTABLISHED -
tcp6 774 0 192.0.2.105:1988 212.9.19.73:36064 ESTABLISHED -
tcp6 92 0 192.0.2.105:1988 46.23.248.19:7164 ESTABLISHED -
tcp6 0 0 192.0.2.105:1988 46.23.248.21:6322 ESTABLISHED 14741/java
tcp6 0 0 192.0.2.105:1988 221.130.39.216:13937 ESTABLISHED 14741/java
tcp6 3051 0 192.0.2.105:1988 211.139.145.104:31239 ESTABLISHED -
tcp6 246 0 192.0.2.105:1988 46.23.248.10:5458 ESTABLISHED -
tcp6 618 0 192.0.2.105:1988 212.9.19.73:20209 ESTABLISHED -
tcp6 1041 0 192.0.2.105:1988 46.23.248.18:7424 ESTABLISHED -
tcp6 0 0 192.0.2.105:1988 46.23.248.10:5065 ESTABLISHED 14741/java
当这种情况发生并且客户端重新连接时,它们往往会正常工作。但它们不会自行重新连接,直到它们遇到相当长的超时。由于当前版本的自定义全双工协议不会确认客户端发送的任何数据,而后者也不会期望服务器定期收到任何传入请求,因此客户端可能需要几天时间才能顺利发送其数据,直到内核的接收队列已满。在服务器(内核)端,应该可以检测到陈旧的套接字,因为客户端会定期发送数据。
因此,假设我对这个问题的解释是正确的,我想知道是否有一个内核参数可以调整,如果用户空间没有及时读取 TCP 连接,内核就会使用 RST 丢弃/关闭 TCP 连接。
我们也欢迎对这里发生的事情提供更好的解释。
答案1
您可以尝试调整TCP 保活更短的值。默认情况下,连接可以闲置两个小时,然后 keepalive 才会启动。
您应使用什么值实际上取决于您的应用程序的功能以及用户的期望或他们如何与之交互。
答案2
我想答案是否定的。
通过替换相关软件已解决问题,但仍欢迎提出想法。