解决处于CLOSE_WAIT状态的连接问题

29

我有一个Java应用程序在Windows上运行的WebLogic 11g中,在几天后会变得无响应。我注意到一个可疑的症状是,即使服务器处于空闲状态,大量连接(约3000个)显示为CLOSE_WAIT状态。由于应用服务器正在管理客户端连接,我不确定是什么原因导致了这种情况。我们还进行了一些回环到同一服务器的Web服务调用,但我相信这些连接会被正确关闭。还有什么其他可能导致这种情况,并且如何排除这样的问题?


你确定你总是在服务器端关闭连接吗? - weekens
他们是否在应用程序变得无响应之前就显示为CLOSE_WAIT? - Robin Green
@weekens- 我不关闭服务器端的连接,WebLogic会自己处理。@Robin- 是的,在一个类似配置的服务器上,我看到连接不断积累,直到服务器崩溃。 - Rob H
6个回答

19

我一直遇到同样的问题,为了解决这个问题,我一直在研究socket。

让我简单说几句话,但是必须先声明,我不是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 连接


5
你在回答中严重混淆了 close_wait 和 time_wait。 - wick
根据TCP FSM规范,这是不正确的。当服务器在发送响应后断开连接时,不会发生CLOSE_WAIT状态。只有当客户端(另一端)启动TCP连接的最终化并且服务器端应用程序未发出close()系统调用时,才会发生CLOSE_WAIT状态(正如Brian White在此线程中所解释的那样)。 - Mindaugas Bernatavičius

19

CLOSE_WAIT 是本地TCP状态机处于的状态,当远程主机发送FIN(关闭其连接),但是本地应用程序尚未做出相同的回复FIN时。此时仍有可能让本地机器发送数据,但是客户端无法接收它(除非它只对连接进行了一半的关闭)。

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

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


4

CLOSE_WAIT状态表示另一端已经发起了连接关闭,但是本地应用程序尚未关闭套接字。

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


2
我发现了这段关于CLOSE_WAIT堆积的引用:“有些东西要么阻止HTTP会话的进展(我们被卡住了,所以最终没有调用close),要么引入了一些错误,防止套接字被关闭。这种情况有很多种可能性。”
思考一下:您的应用程序在处理请求时是否会卡住?或者WebLogic本身是否会出现这种情况?
检查一下:您可以进行Java线程转储(在Linux的Oracle JVM上可以使用kill -SIGQUIT进行转储),以尝试查看是否确实有任何线程被卡住?
检查客户端:首先,找出连接到CLOSE_WAIT套接字的客户端的IP地址或主机名。然后,查看这些客户端是否有任何可疑活动。

2
问题是在WebLogic中将“使用JSSE SSL”设置为true时触发了一个错误。对于我们的应用程序来说,使用WebLogic自己的SSL实现而不是JSSE并不是问题,因此我只需取消选中该设置即可解决问题。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接