对卡在 CLOSE_WAIT 状态的连接进行故障排除

Posted

技术标签:

【中文标题】对卡在 CLOSE_WAIT 状态的连接进行故障排除【英文标题】:Troubleshooting connections stuck in CLOSE_WAIT status 【发布时间】:2011-08-03 22:13:39 【问题描述】:

我有一个 Java 应用程序在 Windows 上的 WebLogic 11g 中运行,几天后它变得无响应。我注意到的一个可疑症状是netstat 中出现了大量连接(大约 3000 个),即使服务器处于空闲状态也是如此,并且状态为 CLOSE_WAIT。由于应用程序服务器正在管理客户端连接,我不确定是什么原因造成的。我们还进行了许多返回到同一服务器的 Web 服务调用,但我相信这些连接会正确关闭。还有什么可能导致此问题以及如何解决此类问题?

【问题讨论】:

你确定你总是关闭服务器端的连接吗? 在应用程序变得无响应之前它们是否显示为 CLOSE_WAIT? @weekens- 我不会关闭服务器端的连接,WebLogic 会。 @Robin- 是的,在类似配置的服务器上,我看到连接在服务器崩溃之前累积。 【参考方案1】:

我一直有同样的问题,我一直在研究套接字来解决这个问题。

让我说几句话,但在此之前我必须说我不是 Java 程序员

我不会解释 close_wait 是什么,因为 Brian White 已经说了应该说的一切。

为避免 close_wait,您需要确保服务器在发送回响应后不会关闭连接,因为首先断开连接的人会卡在 close_wait 和 time_wait 中。因此,如果您的服务器卡在 close_wait 中,它会告诉我它在发送响应后正在断开连接。

你应该通过做一些事情来避免这种情况。

1 - 如果您的客户端应用程序未使用 http 1.1 协议,您必须将其设置为使用该协议,因为 'keep-alive http 标头选项。

2 - 如果您的客户端运行的是 http 1.1 并且不起作用,或者,如果您必须使用 http 1.0,则应设置连接请求标头属性:

connection: keep-alive

这告诉服务器客户端和服务器都不应在完成请求后断开连接。通过这样做,您的服务器不会在收到每个请求后断开连接。

3 - 在您的客户端中,重用您的套接字。例如,如果您在循环中创建大量套接字客户端,您应该创建一次套接字,并且每次需要发送请求时它们都会使用它。我在我的应用程序中使用的方法是拥有一个套接字池并获得一个可用的套接字(它已经连接到服务器并且它具有 keep-alive 属性)。然后我使用它,完成后我将它放回池中以供重复使用。

4 - 如果您在发送请求后确实需要断开连接,请确保您的客户端这样做并保留connection: keep-alive

是的,当您在服务器端有很多 close_waits 或 time_waits 时,您可能会遇到问题。

查看此 [链接][1],它解释了 keep-alive 是什么。

我希望这会有所帮助。有了这些东西,我设法解决了我的问题。

[1]:http://www.w3.org/Protocols/HTTP/1.1/draft-ietf-http-v11-spec-01.html#Persistent 连接

【讨论】:

我认为您在回答中严重混淆了 close_wait 和 time_wait。 根据 TCP FSM 规范,这是不正确的。当服务器在发送响应后断开连接时,不会发生 CLOSE_WAIT。这是当客户端(另一端)启动 TCP 连接的最终确定并且服务器端的应用程序未发出 close() 系统调用时(正如 Brian White 在此线程中解释的那样)【参考方案2】:

这可能意味着您没有从您的 accept() 调用中调用套接字上的“关闭”。

【讨论】:

【参考方案3】:

问题是通过在 webLogic 中将“使用 JSSE SSL”设置为 true 触发的错误。使用 WebLogic 自己的 SSL 实现而不是 JSSE 对我们的应用程序来说不是问题,所以我只是取消选中该设置,问题就消失了。

【讨论】:

【参考方案4】:

CLOSE_WAIT 是本地 TCP 状态机在远程主机发送 FIN(关闭其连接)但本地应用程序没有执行相同操作并发送回复 FIN 时所处的状态。此时本地机器仍然可以发送数据,尽管客户端无法接收数据(除非它只在连接上半关闭)。

当远程主机关闭(发送 FIN)时,您的本地应用程序将收到某种事件(这是基本 C 库中套接字上的“读取”事件),但从该连接读取将返回错误表示连接已关闭。此时本地应用程序应该关闭连接。

我对Java知之甚少,对WebLogic一无所知,但我认为应用程序可能没有正确处理读取错误,因此从未关闭连接。

【讨论】:

【参考方案5】:

CLOSE_WAIT状态表示对方已经发起关闭连接,但是本端的应用程序还没有关闭socket。

听起来您的本地应用程序中存在错误。

【讨论】:

【参考方案6】:

我发现这句话是关于 CLOSE_WAIT 堆积的:“有些东西要么阻止了 发生在 HTTP 会话中(我们被卡住了,所以永远不会结束调用 close),或者引入了一些阻止套接字关闭的错误。发生这种情况的方式有很多种。”

想一想:在处理请求时,您的应用程序是否会卡住?还是 WebLogic 本身?

检查:您能否执行 Java 线程转储(kill -SIGQUIT 可用于 Linux 的 Oracle JVM)来尝试查看实际上是否有任何线程被卡住了?

检查客户端:首先,找出连接到 CLOSE_WAIT 套接字的客户端的 IP 地址或主机名。然后,看看这些客户端是否发生了任何可疑的事情。

【讨论】:

以上是关于对卡在 CLOSE_WAIT 状态的连接进行故障排除的主要内容,如果未能解决你的问题,请参考以下文章

端口状态说明 LISTENINGESTABLISHEDTIME_WAIT及CLOSE_WAIT

端口状态说明 LISTENINGESTABLISHEDTIME_WAIT及CLOSE_WAIT

LISTENINGESTABLISHEDTIME_WAIT及CLOSE_WAIT 端口状态说明

[tcp] 服务端大量close_wait 和 time_wait状态

记一次CLOSE_WAIT多的故障

HttpClient当HTTP连接的时候出现大量CLOSE_WAIT连接(转)