httpclient使用连接池

来源:互联网 发布:网络设计是干什么的 编辑:程序博客网 时间:2024/04/30 08:33
httpclient是java开发中非常常见的一种访问网络资源的方式了,本位主要说明多线程环境下HttpClient连接池的使用。
虽说http协议时无连接的,但毕竟是基于tcp的,底层还是需要和服务器建立连接的。对于需要从同一个站点抓取大量网页的程序,应该使用连接池,否则每次抓取都和Web站点建立连接、发送请求、获得响应、释放连接,一方面效率不高,另一方面稍不小心就会疏忽了某些资源的释放、导致站点拒绝连接(很多站点会拒绝同一个ip的大量连接、防止DOS攻击)。

HttpClient从4.2开始抛弃了先前的SingleClientConnManager和ThreadSafeConnManger,取而代之的是BasicClientConnectionManager和PoolingClientConnectionManager。
BasicClientConnectionManager内部只维护一个活动的connection,尽管这个类是线程安全的,但是最好在一个单独的线程中重复使用它。如果在同一个BasicClientConnectionManager对象中,多次执行http请求,后继请求与先前请求是同一个route,那么BasicClientConnectionManager会使用同一个连接完成后续请求,否则,BasicClientConnectionManager会将先前的connection关闭,然后为后续请求创建一个新的连接。换句话说,BasicClientConnectionManager会尽力复用先前的连接(注意:创建连接和销毁连接都是不小的开销),因此,如果对同一个service有多个连续请求,应该尽量使用同一个BasicClientConnectionManager完成。
PoolingClientConnectionManager可以在多线程中使用,连接按照route被缓存(pooled),当后续的请求route已经在pool中存在,就会使用pool中先前使用的connection获取请求结果。PoolingClientConnectionManager对每个router维护的connection数目有上限要求,默认情况下,每个router最多维护两个并发线程的connection连接,整个pool最多容纳20个并发的connections。当然可以通过设置来修改这些限制。

BasicClientConnectionManager的示例:
public static void basicClientTest() throws ClientProtocolException, IOException{
       HttpClient httpClient = new DefaultHttpClient();
       HttpGet httpGet = new HttpGet("http://m.weather.com.cn/data/101010100.html");
       HttpResponse response = httpClient.execute(httpGet);
       String result = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
       System.out.println(result);
       httpClient.getConnectionManager().shutdown();
}

PoolingClientConnectionManager连接池的例程如下:
SchemeRegistry schemeRegistry = new SchemeRegistry();  
schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));  
schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));  
PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry);  
HttpHost googleResearch = new HttpHost("research.google.com", 80);  
HttpHost wikipediaEn = new HttpHost("en.wikipedia.org", 80);  
cm.setMaxPerRoute(new HttpRoute(googleResearch), 30);  
cm.setMaxPerRoute(new HttpRoute(wikipediaEn), 50);  

1.首先配置最大连接数和最大路由连接数,如果你要连接的url只有一个,两个必须配置成一样,否则只会取最小值。(这是个坑,默认最大连接是20,每个路由最大连接是2)
2.最好配置httpclient连接等待时间,和相应时间。否则就会一直等待。
httpParams = new BasicHttpParams();  
httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,CONNECT_TIMEOUT);  
httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, READ_TIMEOUT);
3. httpclient必须releaseconnection,但不是abort。因为releaseconnection是归还连接到连接池,而abort是直接抛弃这个连接,而且占用连接池的数目。
HttpGet httpGet = new HttpGet(searchurl);
httpGet.releaseConnection();
4. httpclient设置的最大连接数绝对不能超过tomcat设置的最大连接数,否则tomcat的连接就会被httpclient连接池一直占用,直到系统挂掉。 
5.可以使用tomcat的长连接和htppclient连接池和合理使用来增加系统响应速度。
cm.setMaxTotal(200);    //创建socket的上线是200
cm.setDefaultMaxPerRoute(20);  //默认对每个指定连接的服务器(指定的ip)可以创建并发20 socket进行访问  
1 0
原创粉丝点击