`
wusuoya
  • 浏览: 641430 次
  • 性别: Icon_minigender_2
  • 来自: 成都
社区版块
存档分类
最新评论

HttpClient4.X 升级 入门 + http连接池使用

 
阅读更多

在一次服务器异常的排查过程当中(服务器异常排查的过程我会另起文章),我们决定使用HttpClient4.X替代HttpClient3.X或者HttpConnection。

为什么使用HttpClient4?主要是HttpConnection没有连接池的概念,多少次请求就会建立多少个IO,在访问量巨大的情况下服务器的IO可能会耗尽。

HttpClient3也有连接池的东西在里头,使用MultiThreadedHttpConnectionManager,大致过程如下:

 

  1. MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();  
  2. HttpClient client = new HttpClient(connectionManager);...// 在某个线程中。  
  3. GetMethod get = new GetMethod("http://jakarta.apache.org/");  
  4. try {  
  5. client.executeMethod(get);// print response to stdout  
  6. System.out.println(get.getResponseBodyAsStream());  
  7. } finally {  
  8. // be sure the connection is released back to the connection   
  9. managerget.releaseConnection();  
  10. }  

 

 

可以看出来,它的方式与jdbc连接池的使用方式相近,我觉得比较不爽的就是需要手动调用releaseConnection去释放连接。对每一个HttpClient.executeMethod须有一个method.releaseConnection()与之匹配。

 

HttpClient4在这点上做了改进,使用我们常用的InputStream.close()来确认连接关闭(4.1版本之前使用entity.consumeContent()来确认内容已经被消耗关闭连接)。具体方式如下:

 

  1. ...HttpClient client = null;InputStream in = null;  
  2. try{  
  3. client = HttpConnectionManager.getHttpClient();  
  4. HttpGet get = new HttpGet();  
  5. get.setURI(new URI(urlPath));  
  6. HttpResponse response = client.execute(get);  
  7. HttpEntity entity =response.getEntity();  
  8. if( entity != null ){   
  9.  in = entity.getContent();  
  10.  ....  
  11. }catch (Exception e){  
  12. ....  
  13. }finally{  
  14. if (in != null){  
  15. try{in.close ();}catch (IOException e){  
  16. e.printStackTrace ();  
  17. }  
  18. }  
  19. }  

 

2012-03-06更新:

有网友提出调用in.close()是否会关闭底层socket,事情是这样的:

 

[plain] view plaincopyprint?
 
  1. 回复kangkang203:感谢你提出的这个问题。  
  2. 首先我文中提出的方法in.close()它会触发一个连接的释放这个连接将重新被连接管理器收回,官网的原文是这么说的:“Closing the input stream will trigger connection release...the underlying connection gets released back to the connection manager”。但是底层的socket是否会被关闭是不一定的,我看了部分源码(EofSensorInputStream)发现,大多数情况socket并不会关闭,而是否关闭socket貌似是由一个Watcher去决定的。所以in.close的调用不会引起socket的关闭。  
  3. 另外,由于http本身我们把它当做“短连接”,所以在一次请求交互完成后仍然打开socket的意义不是很大,毕竟它不像长连接那样在一个连接建立之后会有很多次数据交互。我们试用连接管理器的更多意义在于它对连接的管理。  


 

 

好说完了连接池的使用流程,现在来说一说连接池在使用时最重要的几个参数。我用4.1的版本实现了一个简单的HttpConnectionManager,代码如下:

 

  1. public class HttpConnectionManager {   
  2.   
  3.     private static HttpParams httpParams;  
  4.     private static ClientConnectionManager connectionManager;  
  5.   
  6.     /** 
  7.      * 最大连接数 
  8.      */  
  9.     public final static int MAX_TOTAL_CONNECTIONS = 800;  
  10.     /** 
  11.      * 获取连接的最大等待时间 
  12.      */  
  13.     public final static int WAIT_TIMEOUT = 60000;  
  14.     /** 
  15.      * 每个路由最大连接数 
  16.      */  
  17.     public final static int MAX_ROUTE_CONNECTIONS = 400;  
  18.     /** 
  19.      * 连接超时时间 
  20.      */  
  21.     public final static int CONNECT_TIMEOUT = 10000;  
  22.     /** 
  23.      * 读取超时时间 
  24.      */  
  25.     public final static int READ_TIMEOUT = 10000;  
  26.   
  27.     static {  
  28.         httpParams = new BasicHttpParams();  
  29.         // 设置最大连接数  
  30.         ConnManagerParams.setMaxTotalConnections(httpParams, MAX_TOTAL_CONNECTIONS);  
  31.         // 设置获取连接的最大等待时间  
  32.         ConnManagerParams.setTimeout(httpParams, WAIT_TIMEOUT);  
  33.         // 设置每个路由最大连接数  
  34.         ConnPerRouteBean connPerRoute = new ConnPerRouteBean(MAX_ROUTE_CONNECTIONS);  
  35.         ConnManagerParams.setMaxConnectionsPerRoute(httpParams,connPerRoute);  
  36.         // 设置连接超时时间  
  37.         HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT);  
  38.         // 设置读取超时时间  
  39.         HttpConnectionParams.setSoTimeout(httpParams, READ_TIMEOUT);  
  40.   
  41.         SchemeRegistry registry = new SchemeRegistry();  
  42.         registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));  
  43.         registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));  
  44.   
  45.         connectionManager = new ThreadSafeClientConnManager(httpParams, registry);  
  46.     }  
  47.   
  48.     public static HttpClient getHttpClient() {  
  49.         return new DefaultHttpClient(connectionManager, httpParams);  
  50.     }  
  51.   
  52. }  

 

 

最大连接数、获取连接的最大等待时间、读取超时时间 这些配置应该比较容易理解,一般的连接池都会有这些配置,比较特别的是 每个路由(route)最大连接数 。

 

什么是一个route?

 

这里route的概念可以理解为 运行环境机器 到 目标机器的一条线路。举例来说,我们使用HttpClient的实现来分别请求 www.baidu.com 的资源和 www.bing.com 的资源那么他就会产生两个route。

 

这里为什么要特别提到route最大连接数这个参数呢,因为这个参数的默认值为2,如果不设置这个参数值默认情况下对于同一个目标机器的最大并发连接只有2个!这意味着如果你正在执行一个针对某一台目标机器的抓取任务的时候,哪怕你设置连接池的最大连接数为200,但是实际上还是只有2个连接在工作,其他剩余的198个连接都在等待,都是为别的目标机器服务的。

 

怎么样蛋疼吧,我是已经有过血的教训了,在切换到HttpClient4.1的起初没有注意到这个配置,最后使得服务承受的压力反而不如从前了,所以在这里特别提醒大家注意。

 

HttpClient4.X 教程下载:

http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/httpclient-contrib/docs/translated-tutorial/httpclient-tutorial-simplified-chinese.pdf

 

关于版本的补充:

网友w2449008821提醒之后我才发现在HttpClient4.1+的版本ConnManagerParams已经被Deprecated了。

我在写这篇日志的时候时候的httpclient 版本是4.0.3,从4.0版本之后ConnManagerParams被Deprecated,没想到一个小版本升级会有这么大变化。

官网教程举例了新的连接池设置:

 

  1. SchemeRegistry schemeRegistry = new SchemeRegistry();  
  2. schemeRegistry.register(  
  3.          new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));  
  4. schemeRegistry.register(  
  5.          new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));  
  6.   
  7. ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(schemeRegistry);  
  8. // Increase max total connection to 200  
  9. cm.setMaxTotalConnections(200);  
  10. // Increase default max connection per route to 20  
  11. cm.setDefaultMaxPerRoute(20);  
  12. // Increase max connections for localhost:80 to 50  
  13. HttpHost localhost = new HttpHost("locahost", 80);  
  14. cm.setMaxForRoute(new HttpRoute(localhost), 50);  
  15.    
  16. HttpClient httpClient = new DefaultHttpClient(cm);  

ConnManagerParams的功能被挪到了 ThreadSafeClientConnManager 和 HttpConnectionParams两个类:

 

 

static ConnPerRoute getMaxConnectionsPerRoute(HttpParams params) 
          Deprecated. use ThreadSafeClientConnManager.getMaxForRoute(org.apache.http.conn.routing.HttpRoute)
static int getMaxTotalConnections(HttpParams params) 
          Deprecated. use ThreadSafeClientConnManager.getMaxTotal()
static long getTimeout(HttpParams params) 
          Deprecated. use HttpConnectionParams.getConnectionTimeout(HttpParams)
static void setMaxConnectionsPerRoute(HttpParams params, ConnPerRoute connPerRoute) 
          Deprecated. use ThreadSafeClientConnManager.setMaxForRoute(org.apache.http.conn.routing.HttpRoute, int)
static void setMaxTotalConnections(HttpParams params, int maxTotalConnections) 
          Deprecated. use ThreadSafeClientConnManager.setMaxTotal(int)
static void setTimeout(HttpParams params, long timeout) 
          Deprecated. use HttpConnectionParams.setConnectionTimeout(HttpParams, int)



 

参考:http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/params/ConnManagerParams.html

http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e638

 

 

httpclient 4.2 以上的版本正确释放链接的方式为

finally {            

            if (response != null) {

                EntityUtils.consumeQuietly(response.getEntity());

           }

           request.abort();

 

}

 

Open Declarationvoid org.apache.http.util.EntityUtils.consumeQuietly(HttpEntity entity)

 

Ensures that the entity content is fully consumed and the content stream, if exists, is closed. The process is done, quietly , without throwing any IOException.

Parameters:
entity
Since:
4.2

 

分享到:
评论

相关推荐

    HttpClient 3.x to HttpComponents HttpClient 4.x

    例如,在HttpClient 3.x中,代码可能会使用`***mons.httpclient.HttpClient`类和`***mons.httpclient.methods.GetMethod`等,而在4.x版本中,这些都被新的API所替代。程序员需要熟悉`org.apache....

    httpclient 4.X版本下载有的带源码包

    2013-11-21 15:31 292,890 httpclient-4.0.2.jar 2017-12-20 12:08 351,132 httpclient-4.1.1.jar 2012-08-03 01:45 451,595 httpclient-4.1.2-sources.jar 2012-08-03 01:44 352,254 httpclient-4.1.2.jar 2012-08-...

    httpclient4.x官方范例

    此外,HTTPClient 4.x提供了更灵活的配置选项,比如连接管理器,允许自定义连接池大小、超时设置等。 1. **连接管理**:在HTTPClient 4.x中,`PoolingHttpClientConnectionManager`是默认的连接管理器,负责创建、...

    HttpClient4.x手动释放底层HTTP连接[借鉴].pdf

    但是,使用HttpClient4.x时需要手动释放底层HTTP连接,否则将造成过高的资源占用。 在HttpClient4.x中,使用完后的HttpClient对象,需要显式地释放其使用的底层HTTP连接。如果不释放,将会导致系统资源的浪费,进而...

    HTTPClient 4.3.X

    标题 "HTTPClient 4.3.X" 涉及的是Apache HttpClient库的一个版本,这是一个广泛使用的Java库,用于实现客户端HTTP通信。这个库为开发者提供了丰富的功能,包括发送HTTP请求,处理响应,管理连接池,处理cookies,...

    httpclient4.3.x及其依赖jar包

    3. **连接管理**:HttpClient提供了强大的连接管理机制,包括连接池,能够有效地复用TCP连接,减少网络延迟。 4. **请求和响应的抽象**:HttpClient将HTTP请求和响应进行了清晰的抽象,方便开发者自定义请求头、...

    可用org.apache.commons.httpclient-3.1.0.jar.zip

    import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods....

    httpclientDemo(4.x与4以下的版本)例子

    这个"HttpclientDemo(4.x与4以下的版本)"示例显然涵盖了HttpClient在不同版本间的使用方法,特别是4.x版本和4.x之前的版本之间的差异。在本文中,我们将深入探讨HttpClient的基本概念、主要功能以及在不同版本中的...

    Java HttpClient 4.x Jar包

    含tutorial,commons-logging-1.1.1, commons-codec-1.4-bin.zip, httpcomponents-client-4.0.3-bin.zip, httpcomponents-core-4.1-bin.zip

    基于SSM+maven+httpClient+jsoup实现小说网站项目源码.zip

    基于SSM+maven+httpClient+jsoup实现小说网站项目源码.zip 基于SSM+maven+httpClient+jsoup实现小说网站项目源码.zip 基于SSM+maven+httpClient+jsoup实现小说网站项目源码.zip 基于SSM+maven+httpClient+jsoup实现...

    httpclient-4.4.1.jar+httpcore-4.2-beta1.jar

    此外,它还允许自定义请求头,实现重试策略,以及支持连接池管理,以优化网络性能。HttpClient 4.4.1引入了一些bug修复和性能改进,以提高其稳定性和效率。 **httpcore-4.2-beta1.jar** Apache HttpCore是...

    httpclient-4.5.2.jar.zip

    3. 使用入门: - **创建HttpClient实例**:使用`HttpClientBuilder`构建器创建HttpClient对象,可以配置连接池大小、超时等参数。 - **构建HttpGet/HttpPost请求**:通过`HttpGet`或`HttpPost`构造HTTP请求,设置...

    HttpClient3.1.jar

    HttpClient3.1.jar是Apache HttpClient库的一个版本,它在Java编程环境中用于实现HTTP客户端通信。这个库被广泛用于开发需要...在新的项目中,开发者通常会考虑使用更新的版本(如HttpClient 4.x)或替代品,如OkHttp。

    HttpClient.zip_HTTP_c++ httpclass_c++ httpclient类_http client c+

    6. **连接管理**:为了提高效率,HttpClient可能会使用连接池来复用TCP连接,减少每次请求的建立和关闭连接的时间开销。 7. **异步处理**:为了支持非阻塞的网络I/O,HttpClient可能提供异步版本的请求方法,如`...

    HttpClient所需jar包(全) httpClient.4.13jar

    2. `httpcore-4.x.x.jar`: 这是HttpClient的基础组件,提供了网络通信的基本功能,如套接字连接和输入/输出流处理。 3. `httpmime-4.x.x.jar`: 这个库扩展了HttpClient,支持在HTTP请求中处理MIME类型的数据,比如...

    基于SSM+maven+httpClient+jsoup实现小说网站项目.zip

    基于SSM+maven+httpClient+jsoup实现小说网站项目.zip基于SSM+maven+httpClient+jsoup实现小说网站项目.zip基于SSM+maven+httpClient+jsoup实现小说网站项目.zip基于SSM+maven+httpClient+jsoup实现小说网站项目.zip...

    httpClient

    2. **多路复用与HTTP/1.1**:HttpClient 4.x支持HTTP/1.1的连接池,通过Keep-Alive优化连接使用,减少了建立和关闭连接的开销,提升了性能。 3. **异步与同步接口**:HttpClient 4.x提供了同步和异步两种执行模型,...

    commons-httpclient-3.0.jar JAVA中使用HttpClient可以用到

    虽然`commons-httpclient-3.0.jar`是一个经典版本,但随着Java的发展,Apache社区已经推出了更现代的HttpClient 4.x系列,提供了更多改进和优化,如更好的线程安全、更丰富的API以及对HTTP/2的支持。因此,建议在新...

Global site tag (gtag.js) - Google Analytics