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

ESTABLISHED 表示正在进行网络连接的数量
TIME_WAIT 表示表示等待系统主动关闭网络连接的数量
CLOSE_WAIT 表示被动等待程序关闭的网络连接数量

上篇文章给出了解决TIME_WAIT太多的方法,本篇文章以HttpClient为例说明解决大量CLOSE_WAIT状态的方法。


HttpClient是大量使用的用于HTTP连接的包,首先需要说明的是HttpClient 3.x和4.x之间API差距很多,不过强烈建议使用4.x的版本。除此之外,4.x中每个x之间也有一些差别(比如一些弃用的类,新增加的类等),这里以4.2.3版本进行说明。

HttpClient使用的HTTP 1.1协议进行连接,相对于HTTP 1.0来说有一个持续连接的增强,为了充分利用持续连接的特性,在一次连接结束之后,即使将HttpResponse使用close方法关闭,并且将调用了HttpGet或HttpPost的releaseConnection方法,示例代码如下:

  1.  HttpGet method = null;
  2.  HttpResponse response = null;
  3.  try {
  4.      method = new HttpGet(url);
  5.      response = client.execute(method);
  6.  } catch(Exception e) {
  7.     
  8.  } finally {
  9.      if(response != null) {
  10.          EntityUtils.consumeQuietly(response.getEntity());
  11.      }
  12.      if(method != null) {
  13.          method.releaseConnection();
  14.      }
  15.  }

这个时候仍然发现连接处于CLOSE_WAIT状态,这是因为HttpClient在执行close的时候,如果发现Response的Header中Connection是Keep-alive则连接不会关闭,以便下次请求相同网站的时候进行复用,这是产生CLOSE_WAIT连接的原因所在。

最简单的一种解决方法在execute方法之前增加Connection: close头信息,HTTP协议关于这个属性的定义如下:

HTTP/1.1 defines the "close" connection option for the sender to signal that the connection will be closed after completion of the response. For example:
	Connection: close 

示例代码如下:

  1.  HttpGet method = null;
  2.  HttpResponse response = null;
  3.  try {
  4.      method = new HttpGet(url);
  5.      method.setHeader(HttpHeaders.CONNECTION"close");
  6.      response = client.execute(method);
  7.  } catch(Exception e) {
  8.     
  9.  } finally {
  10.      if(response != null) {
  11.          EntityUtils.consumeQuietly(response.getEntity());
  12.      }
  13.      if(method != null) {
  14.          method.releaseConnection();
  15.      }
  16.  }

当然,也有人建议每次请求之后关闭client,但这一点不符合HttpClient设计的原则——复用。如果每次连接完成之后就关闭连接,效率太低了。因此,需要使用PoolingClientConnectionManager,并且设置maxTotal(整个连接池里面最大连接数,默认为20)和defaultMaxPerRoute(每个主机的最大连接数,默认为2),另外client还有一个ClientPNames.CONN_MANAGER_TIMEOUT参数,用来设置当连接不够获取新连接等待的超时时间,默认和CoreConnectionPNames.CONNECTION_TIMEOUT相同。可以根据实际情况对PoolingClientConnectionManager进行设置,以达到效率最优。

还有一种情况也会造成大量CLOSE_WAIT连接,即HttpResponse的状态码不是200的时候,需要及时调用method.abort()方法对连接进行释放,详细可以参考这篇文章

参考资料:
使用httpclient必须知道的参数设置及代码写法、存在的风险
解决:HttpClient导致应用出现过多Close_Wait的问题
Using HttpClient Properly to Avoid CLOSE_WAIT TCP Connections
close_wait troubleshooting
Using HttpClient properly to avoid CLOSE_WAIT TCP connections
HttpClient连接池抛出大量ConnectionPoolTimeoutException: Timeout waiting for connection异常排查
httpclient4.2.1 连接池
爬虫简单示例,用httpClient4.2.1实现(转载)

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HttpClient close_wait不释放是指当HttpClient执行完请求后,关闭连接后却不能及时释放连接出现close_wait状态,可能会导致资源的浪费和程序性能的降低。这种情况通常发现在服务器的TCP连接数一直在增加,却一直处于close_wait状态,并且ClientSocketImpl的状态一直是CLOSED_WAIT,造成资源的浪费和服务器处理能力的下降。 造成HttpClient close_wait不释放的原因可能有以下几点: 1. 连接池没有及时释放连接HttpClient有一个默认的连接池管理器,如果连接池同时被多个线程调用,可能会出现连接池没有及时释放连接情况,导致close_wait状态的产生。 2. Http客户端没有及时关闭连接。有些Http客户端请求完成后不主动释放连接,导致连接一直处于close_wait状态。 3. 服务器没有及时关闭连接。如果服务器没有在超时时间内关闭连接,那么连接就会一直处于close_wait状态。 解决HttpClient close_wait不释放的方法有以下几点: 1. 使用HttpClient连接池管理器时,需要设置合理的连接超时时间和请求超时时间,及时关闭闲置连接或者过期的连接。 2. 在Http客户端请求完成后,及时关闭连接,避免连接一直处于close_wait状态。 3. 调整服务器的超时时间,及时关闭连接。 4. 调整服务器的TCP/IP协议参数,设置合理的TIME_WAIT时间。 总之,为了避免出现close_wait状态的连接,需要在使用HttpClient连接池管理器时,合理调整连接超时时间和请求超时时间,并在请求完成后及时释放连接,避免资源的浪费和程序性能的降低。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值