httpclient連接池的使用

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進行訪問  


參考:
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e467
http://www.tuicool.com/articles/2eQ7Zj#userconsent#
等等

發佈了311 篇原創文章 · 獲贊 2448 · 訪問量 257萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章