1. HttpClient client = new HttpClient();
  2. HttpMethod method = new GetMethod("http://www.apache.org");
  3. try {
  4. client.executeMethod(method);
  5. byte[] responseBody = null;
  6. responseBody = method.getResponseBody();
  7. } catch (HttpException e) {
  8. // TODO Auto-generated catch block
  9. e.printStackTrace();
  10. } catch (IOException e) {
  11. // TODO Auto-generated catch block
  12. e.printStackTrace();
  13. }finally{
  14. method.releaseConnection();
  15. }

大部分人使用HttpClient都是使用类似上面的事例代码,包括Apache官方的例子也是如此。最近我在使用HttpClient是发现一次循环发送大量请求到服务器会导致APACHE服务器的链接被占满,后续的请求便排队等待。 
我服务器端APACHE的配置

  1. Timeout 30
  2. KeepAlive On   #表示服务器端不会主动关闭链接
  3. MaxKeepAliveRequests 100
  4. KeepAliveTimeout 180

因此这样的配置就会导致每个链接至少要过180S才会被释放,这样在大量请求访问时就必然会造成链接被占满,请求等待的情况。 
在通过DEBUH后发现HttpClient在method.releaseConnection()后并没有把链接关闭,这个方法只是将链接返回给connection manager。如果使用HttpClient client = new HttpClient()实例化一个HttpClient connection manager默认实现是使用SimpleHttpConnectionManager。SimpleHttpConnectionManager有个构造函数如下

  1. /**
  2. * The connection manager created with this constructor will try to keep the
  3. * connection open (alive) between consecutive requests if the alwaysClose
  4. * parameter is set to <tt>false</tt>. Otherwise the connection manager will
  5. * always close connections upon release.
  6. *
  7. * @param alwaysClose if set <tt>true</tt>, the connection manager will always
  8. *    close connections upon release.
  9. */
  10. public SimpleHttpConnectionManager(boolean alwaysClose) {
  11. super();
  12. this.alwaysClose = alwaysClose;
  13. }

看方法注释我们就可以看到如果alwaysClose设为true在链接释放之后connection manager 就会关闭链。在我们HttpClient client = new HttpClient()这样实例化一个client时connection manager是这样被实例化的

  1. this.httpConnectionManager = new SimpleHttpConnectionManager();

因此alwaysClose默认是false,connection是不会被主动关闭的,因此我们就有了一个客户端关闭链接的方法。 
方法一: 
把事例代码中的第一行实例化代码改为如下即可,在method.releaseConnection();之后connection manager会关闭connection 。

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

方法二: 
实例化代码使用:HttpClient client = new HttpClient(); 
在method.releaseConnection();之后加上

  1. ((SimpleHttpConnectionManager)client.getHttpConnectionManager()).shutdown();

shutdown源代码很简单,看了一目了然

  1. public void shutdown() {
  2. httpConnection.close();
  3. }

方法三: 
实例化代码使用:HttpClient client = new HttpClient(); 
在method.releaseConnection();之后加上 
client.getHttpConnectionManager().closeIdleConnections(0);此方法源码代码如下:

  1. public void closeIdleConnections(long idleTimeout) {
  2. long maxIdleTime = System.currentTimeMillis() - idleTimeout;
  3. if (idleStartTime <= maxIdleTime) {
  4. httpConnection.close();
  5. }
  6. }

将idleTimeout设为0可以确保链接被关闭。 
以上这三种方法都是有客户端主动关闭TCP链接的方法。下面再介绍由服务器端自动关闭链接的方法。 
方法四: 
代码实现很简单,所有代码就和最上面的事例代码一样。只需要在HttpMethod method = new GetMethod("http://www.apache.org");加上一行HTTP头的设置即可

  1. method.setRequestHeader("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 
现在再说一下客户端关闭链接和服务器端关闭链接的区别。如果采用客户端关闭链接的方法,在客户端的机器上使用netstat –an命令会看到很多TIME_WAIT的TCP链接。如果服务器端主动关闭链接这中情况就出现在服务器端。 
参考WIKI上的说明http://wiki.apache.org/HttpComponents/FrequentlyAskedConnectionManagementQuestions 
The TIME_WAIT state is a protection mechanism in TCP. The side that closes a socket connection orderly will keep the connection in state TIME_WAIT for some time, typically between 1 and 4 minutes. 
TIME_WAIT的状态会出现在主动关闭链接的这一端。TCP协议中TIME_WAIT状态主要是为了保证数据的完整传输。具体可以参考此文档: 
http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html#ss2.7 
另外强调一下使用上面这些方法关闭链接是在我们的应用中明确知道不需要重用链接时可以主动关闭链接来释放资源。如果你的应用是需要重用链接的话就没必要这么做,使用原有的链接还可以提供性能

HttpClient——连接关闭的更多相关文章

  1. HttpClient如何 关闭连接(转)

    ava代码 HttpClient client = new HttpClient(); HttpMethod method = new GetMethod("http://www.apach ...

  2. HttpClient连接池的连接保持、超时和失效机制

    HTTP是一种无连接的事务协议,底层使用的还是TCP,连接池复用的就是TCP连接,目的就是在一个TCP连接上进行多次的HTTP请求从而提高性能.每次HTTP请求结束的时候,HttpClient会判断连 ...

  3. HttpClient连接池抛出大量ConnectionPoolTimeoutException: Timeout waiting for connection异常排查

    转自: http://blog.csdn.net/shootyou/article/details/6615051 今天解决了一个HttpClient的异常,汗啊,一个HttpClient使用稍有不慎 ...

  4. Http持久连接与HttpClient连接池

    一.背景 HTTP协议是无状态的协议,即每一次请求都是互相独立的.因此它的最初实现是,每一个http请求都会打开一个tcp socket连接,当交互完毕后会关闭这个连接. HTTP协议是全双工的协议, ...

  5. Http 持久连接与 HttpClient 连接池

    一.背景 HTTP协议是无状态的协议,即每一次请求都是互相独立的.因此它的最初实现是,每一个http请求都会打开一个tcp socket连接,当交互完毕后会关闭这个连接. HTTP协议是全双工的协议, ...

  6. HttpClient连接池

    HttpClient连接池,发现对于高并发的请求,效率提升很大.虽然知道是因为建立了长连接,导致请求效率提升,但是对于内部的原理还是不太清楚.后来在网上看到了HTTP协议的发展史,里面提到了一个属性C ...

  7. httpClient 连接池问题出现403.9

    困扰了半个月时间终于找到连接池的问题,由于调用第三方有异常导致连接不能及时释放 所以写了一个定时扫描释放连接 监控连接池释放连接: public static class IdleConnection ...

  8. (五)HttpClient 连接超时及读取超时

    第一节: HttpClient 连接超时及读取超时 HttpClient连接超时及读取超时 httpClient在执行具体http请求时候 有一个连接的时间和读取内容的时间: HttpClient连接 ...

  9. HttpClient连接超时及读取超时

    HttpClient连接超时及读取超时 httpClient在执行具体http请求时候 有一个连接的时间和读取内容的时间: HttpClient连接时间 所谓连接的时候 是HttpClient发送请求 ...

随机推荐

  1. 树莓派学习:源码方式安装opencv

    1:下载若干依赖项: 更新软件源:sudo apt-get update/upgrade; 依次安装一下依赖项:   sudo apt-get install build-essential   su ...

  2. 项目中用到的logback列子

    <?xml version="1.0" encoding="UTF-8"?> <configuration> <appender ...

  3. ubuntu vnc install

    windows & ubuntu http://www.jb51.net/os/Ubuntu/104948.html ubuntu & ubuntu https://www.digit ...

  4. Informix SDK對比

    一.基本信息對比 表 1. Informix .NET Provider 和 IBM Data Server .NET Provider 的对比 特性 IBM Informix .NET Provid ...

  5. 如何构建日均千万PV Web站点

    http://www.cnblogs.com/xiaocen/p/3723839.html http://www.cnblogs.com/xiaocen/p/3726763.html http://w ...

  6. C++学习35 模板中的函数式参数

    C++对模板类的支持比较灵活,模板类的参数中除了可以有类型参数,还可以有普通参数.例如: template<typename T, int N> class Demo{ }; N 是一个普 ...

  7. 查看mysql数据库引擎

    1.查看支持的引擎 show engines; 2.查看当前引擎 show variables like '%storage_engine%'

  8. 如何将MVC Areas中的某一个页设为起始页

    area的默认页: routes.MapRoute( name: "MyArea", url: "{controller}/{action}/{id}", de ...

  9. MySql 申明变量以及赋值

    sql server中变量要先申明后赋值: 局部变量用一个@标识,全局变量用两个@(常用的全局变量一般都是已经定义好的): 申明局部变量语法:declare @变量名 数据类型:例如:declare ...

  10. rman异机恢复(RAC双节点恢复到单节点)

    一.数据库全备 RUN {ALLOCATE CHANNEL ch00 DEVICE TYPE disk;ALLOCATE CHANNEL ch01 DEVICE TYPE disk;backup as ...