简体   繁体   English

多个完整的HTTP请求处于TCP CLOSE_WAIT状态

[英]Multiple complete HTTP requests stuck in TCP CLOSE_WAIT state

I have a Java and Tomcat-based server application which initiates many outbound HTTP requests to other web sites. 我有一个基于Java和Tomcat的服务器应用程序,它启动了许多到其他网站的出站HTTP请求。 We use Jakarta's HTTP Core/Client libraries, very latest versions. 我们使用雅加达的HTTP Core / Client库,这是最新版本。

The server locks up at some point since all its worker threads are stuck trying to close completed HTTP connections. 由于所有工作线程都被卡住,试图关闭完整的HTTP连接,因此服务器在某个时候锁定。 Using 'lsof' reveals a bunch of sockets stuck in TCP CLOSE_WAIT state. 使用“ lsof”可显示一堆套接字处于TCP CLOSE_WAIT状态。

This doesn't happen for all, or even most connections. 对于所有甚至大多数连接,都不会发生这种情况。 In fact, I saw it before and resolved it by making sure to set the Connection: Close response header. 实际上,我之前看过它,并通过确保设置Connection:Close响应标头来解决了它。 So that makes me think it may be bad behavior of remote servers. 因此,我认为这可能是远程服务器的不良行为。

It may have come up again since I moved the app to a totally new service provider -- different OS, network situation. 自从我将应用程序移至全新的服务提供商(不同的操作系统,网络情况)后,情况可能再次出现。

But, I am still at a loss as to what I could do, if anything, to work around this. 但是,我仍然无所适从以解决此问题。 Some poking around on the internet didn't turn up anything I'm not already doing. 一些在互联网上闲逛并没有发现我尚未做的任何事情。 Just thought I'd ask if anyone has seen and solved this? 只是以为我会问是否有人看到并解决了这个问题?

I'm not sure how much you know about TCP. 我不确定您对TCP有多少了解。 A TCP client ends up in the CLOSE_WAIT state when it is in the ESTABLISHED state and receives a FIN packet. TCP客户端处于ESTABLISHED状态并收到FIN数据包时,最终以CLOSE_WAIT状态结束。 The CLOSE_WAIT state means that it is waiting to receive a close command from the application layer - in this case, that means it's waiting for close() to be called on the socket. CLOSE_WAIT状态意味着它正在等待从应用程序层接收close命令-在这种情况下,这意味着它正在等待在套接字上调用close()

So, my guess would be that calling close() in the worker threads will fix the problem. 因此,我的猜测是在工作线程中调用close()将解决此问题。 Or are you already doing this? 还是您已经在这样做?

I believe I might have found a solution -- at least, these changes, together, seem to have made the problem go away. 我相信我可能已经找到了解决方案-至少,这些变化在一起似乎使问题消失了。

  • Call HttpEntity.consumeContent() after you're done reading from its InputStream, to double-check the content is consumed and the framework releases the connection 从InputStream中读取完后,调用HttpEntity.consumeContent(),以仔细检查内容是否已消耗以及框架释放连接
  • For good measure, I call ClientConnectionManager.closeExpiredConnections() and ClientConnectionManager.closeIdleConnections(0L, TimeUnit.MILLISECONDS) just after this, to press the framework to release anything it's done with right away. 为了达到良好的效果,在此之后,我立即调用ClientConnectionManager.closeExpiredConnections()和ClientConnectionManager.closeIdleConnections(0L,TimeUnit.MILLISECONDS),以按下框架以立即释放完成的所有操作。 This might be overkill. 这可能是过大的。

OK the above didn't quite do the trick. 确定以上并没有完全解决问题。 In the end, I had to use a SingleClientConnManager, and create and shut it down for every request. 最后,我必须使用SingleClientConnManager,并针对每个请求创建并关闭它。 This did the trick. 这成功了。 I assume that this is what's needed to make sure the connection is closed. 我认为这是确保连接关闭所需要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM