1. 程式人生 > >httpclient4.5.5 PoolingHttpClientConnectionManager

httpclient4.5.5 PoolingHttpClientConnectionManager

    今天在做騰訊網址安全檢測API接入時用到了org.apache.httpcomponents.httpclient-4.5.5這個包,當初在main方法裡測試的時候發現從請求到響應大概要用0.6s的時間,但是在springboot應用裡面使用的時候,第一次請求用了0.4s左右,第二次就只要0.1s左右,很驚訝,然後想是不是連線池的作用,查詢過程如下:

    1.首先在本地,在將程式執行起來後先不進行請求,使用 jmap -histo:live 19144 > d://a.txt 命令(參考https://www.cnblogs.com/anjijiji/p/6239395.html)將JVM中存活的所有物件列印到檔案中,在檔案中檢視是否存在org.apache.http開頭包名的類,發現找不到。

    2.使用postman進行一次API請求,然後在使用 jmap -histo:live 19144 > d://a.txt 將檔案覆蓋後進行檢視,發現在檔案中找到幾個關於org.apache.http.impl.conn開頭的幾個類,將有關連線池的類列出如下:

    org.apache.http.impl.conn.CPool

    org.apache.http.impl.conn.CPoolEntry

    org.apache.http.impl.conn.PoolingHttpClientConnectionManager

 

    PoolingHttpClientConnectionManager是一個HttpClientConnection的連線池封裝,可以為多執行緒提供併發請求服務。主要作用就是分配連線,回收連線等,同一個route的請求,會優先使用連線池提供的空閒長連線;CPoolEntry是ManagedHttpClientConnection的封裝,包含具體的一個連線的資訊;CPool是繼承AbstractConnPool的一個連線池實現,PoolingHttpClientConnectionManager在進行具體的分配連線,回收連接獲時實際上呼叫的是CPool。

    

    只介紹cpool幾個屬性(供參考):

        routeToPool: 具體的路由粒度對應的連線池

        leased:    已經被租用的連線(正在被使用的)

        available:    空閒連線

        pending:    正在等待獲取連線佇列

        maxPerRoute:    每個路由上最大的連線數(不能超過連線池總連線數)

        defaultMaxPerRoute:    預設的每個路由上最大的連線數(不能超過連線池總連線數)

        maxTotal:    連線池最大的連線數

        validateAfterInactivity:空閒永久連線檢查間隔,這個牽扯的還比較多官方推薦使用這個來檢查永久連結的可用性,而不推薦每次請求的時候才去檢查(ms)

   3.在知道以上的原理之後,下面列出具體配置程式碼(歡迎指出錯誤和共同交流!)

public class UrlUtil {
    public static final Logger logger = LoggerFactory.getLogger(UrlUtil.class);

    private static CloseableHttpClient httpClient = null;//
    static {
        PoolingHttpClientConnectionManager clientConnectionManager = new PoolingHttpClientConnectionManager();
        clientConnectionManager.setValidateAfterInactivity(2000);//檢測有效連線的間隔
        clientConnectionManager.setMaxTotal(50);//設定連線池最大數量
        clientConnectionManager.setDefaultMaxPerRoute(50);//設定預設單個路由的最大連線數(由於本處只使用一個路由地址所以設定為連線池大小)
        httpClient = HttpClients.createMinimal(clientConnectionManager);
    }

    /**
     * 檢測URL安全,騰訊網址安全API(部分程式碼)
     * @param urlString
     * @return
     * @throws Exception
     */
    public static void urlSafe(String urlString) throws Exception {

        CloseableHttpResponse response = null;
        try {
            HttpPost httpPost = new HttpPost("http://www.cloud.urlsec.qq.com");
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectionRequestTimeout(1000)//設定連線伺服器超時時間
                    .setConnectTimeout(1000)//設定從連線池獲取可用連線的時間
                    .setSocketTimeout(1000)//設定獲取資料的超時時間
                    .build();
            httpPost.setConfig(requestConfig);
            HttpEntity entity = new StringEntity(params,"utf-8");
            httpPost.setEntity(entity);
            httpPost.setHeader("Content-type", "application/json");
            response = httpClient.execute(httpPost);
        } catch (Exception e) {
            throw e;
        }finally {
            if (null != response) {
                response.close();
            }
        }
    }

}

參考文章:https://www.cnblogs.com/shoren/p/httpclient-leaseConnection.html