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