今天在作騰訊網址安全檢測API接入時用到了org.apache.httpcomponents.httpclient-4.5.5這個包,當初在main方法裏測試的時候發現從請求到響應大概要用0.6s的時間,可是在springboot應用裏面使用的時候,第一次請求用了0.4s左右,第二次就只要0.1s左右,很驚訝,而後想是否是鏈接池的做用,查找過程以下:html
1.首先在本地,在將程序運行起來後先不進行請求,使用 jmap -histo:live 19144 > d://a.txt 命令(參考https://www.cnblogs.com/anjijiji/p/6239395.html)將JVM中存活的全部對象打印到文件中,在文件中查看是否存在org.apache.http開頭包名的類,發現找不到。spring
2.使用postman進行一次API請求,而後在使用 jmap -histo:live 19144 > d://a.txt 將文件覆蓋後進行查看,發如今文件中找到幾個關於org.apache.http.impl.conn開頭的幾個類,將有關鏈接池的類列出以下:apache
org.apache.http.impl.conn.CPooljson
org.apache.http.impl.conn.CPoolEntry安全
org.apache.http.impl.conn.PoolingHttpClientConnectionManagerspringboot
PoolingHttpClientConnectionManager是一個HttpClientConnection的鏈接池封裝,能夠爲多線程提供併發請求服務。主要做用就是分配鏈接,回收鏈接等,同一個route的請求,會優先使用鏈接池提供的空閒長鏈接;CPoolEntry是ManagedHttpClientConnection的封裝,包含具體的一個鏈接的信息;CPool是繼承AbstractConnPool的一個鏈接池實現,PoolingHttpClientConnectionManager在進行具體的分配鏈接,回收鏈接獲時實際上調用的是CPool。服務器
只介紹cpool幾個屬性(供參考):多線程
routeToPool: 具體的路由粒度對應的鏈接池併發
leased: 已經被租用的鏈接(正在被使用的)app
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