HttpClient release 与 close connection

Apache commons 系列的HttpClient 相信你们都用过,选择它而非JDK 的java.net.HttpURLConnection ,是为了使用HttpClient 封装的几个实用的功能。html

目前使用最多的版本仍是httpclient-3.x ,在官网http://hc.apache.org/httpclient-3.x/tutorial.html 有这么一段示例代码:java

 

 
  1. import org.apache.commons.httpclient.*;apache

  2. import org.apache.commons.httpclient.methods.*;网络

  3. import org.apache.commons.httpclient.params.HttpMethodParams;多线程

  4.  
  5. import java.io.*;并发

  6.  
  7. public class HttpClientTutorial {ide

  8.  
  9. private static String url = "http://www.apache.org/";this

  10.  
  11. public static void main(String[] args) {url

  12. // Create an instance of HttpClient..net

  13. HttpClient client = new HttpClient();

  14.  
  15. // Create a method instance.

  16. GetMethod method = new GetMethod(url);

  17.  
  18. // Provide custom retry handler is necessary

  19. method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,

  20. new DefaultHttpMethodRetryHandler(3, false));

  21.  
  22. try {

  23. // Execute the method.

  24. int statusCode = client.executeMethod(method);

  25.  
  26. if (statusCode != HttpStatus.SC_OK) {

  27. System.err.println("Method failed: " + method.getStatusLine());

  28. }

  29.  
  30. // Read the response body.

  31. byte[] responseBody = method.getResponseBody();

  32.  
  33. // Deal with the response.

  34. // Use caution: ensure correct character encoding and is not binary data

  35. System.out.println(new String(responseBody));

  36.  
  37. } catch (HttpException e) {

  38. System.err.println("Fatal protocol violation: " + e.getMessage());

  39. e.printStackTrace();

  40. } catch (IOException e) {

  41. System.err.println("Fatal transport error: " + e.getMessage());

  42. e.printStackTrace();

  43. } finally {

  44. // Release the connection.

  45. method.releaseConnection();

  46. }

  47. }

  48. }


大部分人也是以这个为规范来使用的,可是注意有一段关于“Release the Connection”的说明:

 

This is a crucial step to keep things flowing. We must tell HttpClient that we are done with the connection and that it can now be reused. Without doing this HttpClient will wait indefinitely for a connection to free up so that it can be reused.

我看得也不是很明白,意思是咱们必须在使用后调用

 

method.releaseConnection();

来告诉HttpClient 这个链接能够重用了。

这个在串行的处理中或许颇有用,可是我所遇到的状况是多线程并发下,不能共享同一个HttpClient 实例,按照官方示例写好代码后,程序跑起来彷佛没什么问题,可是随着时间的累计,有一天忽然发现这个模块不工做了,查看了一下当前的网络链接,这个java 程序同一个地址保持着200多个CLOSE_WAIT 的链接,好吧,链接没有释放。

为何没有释放?查看doc,有这样的说明:

 

Releases the connection being used by this HTTP method. In particular the connection is used to read the response(if there is one) and will be held until the response has been read. If the connection can be reused by other HTTP methods it is NOT closed at this point.


注意最后一句,若是该链接能够重用则不关闭,是“能够重用”,固然能够重用了,就在那儿等着我去重用,但是我都是新建的实例,怎么重用

查看源码,找到HttpClient 的构造方法,有一个能够指定HttpConnectionManager ,而后这个HttpConnectionManager 又有一个实现的构造:

 

 
  1. public SimpleHttpConnectionManager(boolean alwaysClose)

  2. The connection manager created with this constructor will try to keep the connection open (alive) between consecutive requests if the alwaysClose parameter is set to false. Otherwise the connection manager will always close connections upon release.

  3. Parameters:

  4. alwaysClose - if set true, the connection manager will always close connections upon release.


显然alawaysClose 的默认值是false ,在释放后链接并不老是会关闭。

因此,必须

 

HttpClient client = new HttpClient(new HttpClientParams(),new SimpleHttpConnectionManager(true));


固然,还有其它的解决方案,找到了一篇文章总结的比较全面:HttpClient容易忽视的细节——链接关闭

相关文章
相关标签/搜索