<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,comments - 227,trackbacks - 0

    http://blog.csdn.net/shootyou/article/details/6415248


    在一次服務(wù)器異常的排查過程當(dāng)中(服務(wù)器異常排查的過程我會(huì)另起文章),我們決定使用HttpClient4.X替代HttpClient3.X或者HttpConnection。

    為什么使用HttpClient4?主要是HttpConnection沒有連接池的概念,多少次請(qǐng)求就會(huì)建立多少個(gè)IO,在訪問量巨大的情況下服務(wù)器的IO可能會(huì)耗盡。

    HttpClient3也有連接池的東西在里頭,使用MultiThreadedHttpConnectionManager,大致過程如下:

    1. MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();  
    2. HttpClient client = new HttpClient(connectionManager);...// 在某個(gè)線程中。  
    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連接池的使用方式相近,我覺得比較不爽的就是需要手動(dòng)調(diào)用releaseConnection去釋放連接。對(duì)每一個(gè)HttpClient.executeMethod須有一個(gè)method.releaseConnection()與之匹配。

     

    HttpClient4在這點(diǎn)上做了改進(jìn),使用我們常用的InputStream.close()來確認(rèn)連接關(guān)閉(4.1版本之前使用entity.consumeContent()來確認(rèn)內(nèi)容已經(jīng)被消耗關(guān)閉連接)。具體方式如下:

    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更新:

    有網(wǎng)友提出調(diào)用in.close()是否會(huì)關(guān)閉底層socket,事情是這樣的:

    1. 回復(fù)kangkang203:感謝你提出的這個(gè)問題。  
    2. 首 先我文中提出的方法in.close()它會(huì)觸發(fā)一個(gè)連接的釋放這個(gè)連接將重新被連接管理器收回,官網(wǎng)的原文是這么說 的:“Closing the input stream will trigger connection release...the underlying connection gets released back to the connection manager”。 但是底層的socket是否會(huì)被關(guān)閉是不一定的,我看了部分源碼(EofSensorInputStream)發(fā)現(xiàn),大多數(shù)情況socket并不會(huì)關(guān)閉, 而是否關(guān)閉socket貌似是由一個(gè)Watcher去決定的。所以in.close的調(diào)用不會(huì)引起socket的關(guān)閉。  
    3. 另外,由于http本身我們把它當(dāng)做“短連接”,所以在一次請(qǐng)求交互完成后仍然打開socket的意義不是很大,畢竟它不像長(zhǎng)連接那樣在一個(gè)連接建立之后會(huì)有很多次數(shù)據(jù)交互。我們?cè)囉眠B接管理器的更多意義在于它對(duì)連接的管理。  

     

    好說完了連接池的使用流程,現(xiàn)在來說一說連接池在使用時(shí)最重要的幾個(gè)參數(shù)。我用4.1的版本實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的HttpConnectionManager,代碼如下:

    1. public class HttpConnectionManager {   
    2.   
    3.     private static HttpParams httpParams;  
    4.     private static ClientConnectionManager connectionManager;  
    5.   
    6.     /** 
    7.      * 最大連接數(shù) 
    8.      */  
    9.     public final static int MAX_TOTAL_CONNECTIONS = 800;  
    10.     /** 
    11.      * 獲取連接的最大等待時(shí)間 
    12.      */  
    13.     public final static int WAIT_TIMEOUT = 60000;  
    14.     /** 
    15.      * 每個(gè)路由最大連接數(shù) 
    16.      */  
    17.     public final static int MAX_ROUTE_CONNECTIONS = 400;  
    18.     /** 
    19.      * 連接超時(shí)時(shí)間 
    20.      */  
    21.     public final static int CONNECT_TIMEOUT = 10000;  
    22.     /** 
    23.      * 讀取超時(shí)時(shí)間 
    24.      */  
    25.     public final static int READ_TIMEOUT = 10000;  
    26.   
    27.     static {  
    28.         httpParams = new BasicHttpParams();  
    29.         // 設(shè)置最大連接數(shù)  
    30.         ConnManagerParams.setMaxTotalConnections(httpParams, MAX_TOTAL_CONNECTIONS);  
    31.         // 設(shè)置獲取連接的最大等待時(shí)間  
    32.         ConnManagerParams.setTimeout(httpParams, WAIT_TIMEOUT);  
    33.         // 設(shè)置每個(gè)路由最大連接數(shù)  
    34.         ConnPerRouteBean connPerRoute = new ConnPerRouteBean(MAX_ROUTE_CONNECTIONS);  
    35.         ConnManagerParams.setMaxConnectionsPerRoute(httpParams,connPerRoute);  
    36.         // 設(shè)置連接超時(shí)時(shí)間  
    37.         HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT);  
    38.         // 設(shè)置讀取超時(shí)時(shí)間  
    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. }  

    最大連接數(shù)、獲取連接的最大等待時(shí)間、讀取超時(shí)時(shí)間 這些配置應(yīng)該比較容易理解,一般的連接池都會(huì)有這些配置,比較特別的是 每個(gè)路由(route)最大連接數(shù)

     

    什么是一個(gè)route?

     

    這里route的概念可以理解為 運(yùn)行環(huán)境機(jī)器 到 目標(biāo)機(jī)器的一條線路。舉例來說,我們使用HttpClient的實(shí)現(xiàn)來分別請(qǐng)求 www.baidu.com 的資源和 www.bing.com 的資源那么他就會(huì)產(chǎn)生兩個(gè)route。

     

    這里為什么要特別提到route最大連接數(shù)這個(gè)參數(shù)呢,因?yàn)檫@個(gè)參數(shù)的默認(rèn)值為2,如果 不設(shè)置這個(gè)參數(shù)值默認(rèn)情況下對(duì)于同一個(gè)目標(biāo)機(jī)器的最大并發(fā)連接只有2個(gè)!這意味著如果你正在執(zhí)行一個(gè)針對(duì)某一臺(tái)目標(biāo)機(jī)器的抓取任務(wù)的時(shí)候,哪怕你設(shè)置連接 池的最大連接數(shù)為200,但是實(shí)際上還是只有2個(gè)連接在工作,其他剩余的198個(gè)連接都在等待,都是為別的目標(biāo)機(jī)器服務(wù)的。

     

    怎么樣蛋疼吧,我是已經(jīng)有過血的教訓(xùn)了,在切換到HttpClient4.1的起初沒有注意到這個(gè)配置,最后使得服務(wù)承受的壓力反而不如從前了,所以在這里特別提醒大家注意。

     

    HttpClient4.X 教程下載:

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


    關(guān)于版本的補(bǔ)充:

    網(wǎng)友w2449008821提醒之后我才發(fā)現(xiàn)在HttpClient4.1+的版本ConnManagerParams已經(jīng)被Deprecated了。

    我在寫這篇日志的時(shí)候時(shí)候的httpclient 版本是4.0.3,從4.0版本之后ConnManagerParams被Deprecated,沒想到一個(gè)小版本升級(jí)會(huì)有這么大變化。

    官網(wǎng)教程舉例了新的連接池設(shè)置:

    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兩個(gè)類:

    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
    posted on 2012-07-16 12:01 SIMONE 閱讀(15672) 評(píng)論(2)  編輯  收藏 所屬分類: JAVA

    FeedBack:
    # re: HttpClient4.X 升級(jí) 入門 + http連接池使用
    2013-04-12 23:07 | 麥咖啡
    感謝作者,很好的內(nèi)容。最近在看httpClient的相關(guān)內(nèi)容,被他的各個(gè)版本的變化都弄瘋了~~~~  回復(fù)  更多評(píng)論
      
    # re: HttpClient4.X 升級(jí) 入門 + http連接池使用
    2013-04-12 23:09 | 麥咖啡
    想問一下作者,關(guān)于Cookie的處理,比如我訪問一個(gè)站點(diǎn),這個(gè)站點(diǎn)在Response里會(huì)寫Cookie, 但是我自己寫的代碼里,卻怎么也拿不到。  回復(fù)  更多評(píng)論
      
    主站蜘蛛池模板: 亚洲日韩精品无码专区网站| 国产成人精品免费午夜app| 亚洲AV无码片一区二区三区| 亚洲中文字幕AV在天堂| 久久精品国产亚洲av麻豆图片| 亚洲成AV人综合在线观看| 亚洲视频在线观看免费视频| 亚洲精品一卡2卡3卡三卡四卡| 亚洲日本视频在线观看| 亚洲午夜精品一区二区公牛电影院 | vvvv99日韩精品亚洲| 最近中文字幕mv免费高清电影 | 久久精品免费视频观看| 久久国产乱子伦精品免费看| 三年片在线观看免费大全电影| 最近中文字幕无免费| 人成午夜免费视频在线观看| 天天操夜夜操免费视频| 免费日本黄色网址| 国内精品久久久久久久亚洲| 久久精品夜色国产亚洲av| 亚洲精品欧洲精品| 亚洲人成网站免费播放| 日韩在线一区二区三区免费视频| 国产97视频人人做人人爱免费| 国产成年无码久久久免费| 222www免费视频| 天天天欲色欲色WWW免费| 亚洲 国产 图片| 亚洲AV成人片色在线观看高潮| 亚洲精品人成电影网| 色偷偷尼玛图亚洲综合| 中文无码日韩欧免费视频| 99久久国产免费中文无字幕| 好吊妞788免费视频播放| 亚洲国产精品狼友中文久久久| 久久青草亚洲AV无码麻豆| 学生妹亚洲一区二区| 国产精品福利在线观看免费不卡| 国产白丝无码免费视频| 女人18毛片水真多免费播放|