HttpClient4.5.2 連線池原理及注意事項
隨著微服務的流行,服務之間的http呼叫越來越多,遇到的問題也比較多,寫這邊文章的目的也是將自己遇到的坑和解決方案跟大家分享
一、為什麼要用Http連線池
1、降低延遲:如果不採用連線池,每次連線發起Http請求的時候都會重新建立TCP連線(經歷3次握手),用完就會關閉連線(4次揮手),如果採用連線池則減少了這部分時間損耗,別小看這幾次握手,本人經過測試發現,基本上3倍的時間延遲
2、支援更大的併發:如果不採用連線池,每次連線都會開啟一個埠,在大併發的情況下系統的埠資源很快就會被用完,導致無法建立新的連線
二、程式碼
1、HttpConnectionManager.java連線池管理類,支援https協議
@Component
public class HttpConnectionManager {
PoolingHttpClientConnectionManager cm = null;
@PostConstruct
public void init() {
LayeredConnectionSocketFactory sslsf = null;
try {
sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("https", sslsf)
.register("http", new PlainConnectionSocketFactory())
.build();
cm =new PoolingHttpClientConnectionManager(socketFactoryRegistry);
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(20);
}
public CloseableHttpClient getHttpClient() {
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();
/*CloseableHttpClient httpClient = HttpClients.createDefault();//如果不採用連線池就是這種方式獲取連線
return httpClient;
}
}
2、連線池消費類:HaoMaiClient.java
@Component
public class HaoMaiClient {
@Autowired
HttpConnectionManager connManager;
public <T> T get(String path,Class<T> clazz){
CloseableHttpClient httpClient=connManager.getHttpClient();
HttpGet httpget = new HttpGet(path);
String json=null;
CloseableHttpResponse response=null;
try {
response = httpClient.execute(httpget);
InputStream in=response.getEntity().getContent();
json=IOUtils.toString(in);
in.close();
} catch (UnsupportedOperationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(response!=null){
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return JSON.parseObject(json, clazz);
}
}
三、原理及注意事項
連線池中連線都是在發起請求的時候建立,並且都是長連線
HaoMaiClient.java中的in.close();作用就是將用完的連線釋放,下次請求可以複用,這裡特別注意的是,如果不使用in.close();而僅僅使用response.close();結果就是連線會被關閉,並且不能被複用,這樣就失去了採用連線池的意義。
連線池釋放連線的時候,並不會直接對TCP連線的狀態有任何改變,只是維護了兩個Set,leased和avaliabled,leased代表被佔用的連線集合,avaliabled代表可用的連線的集合,釋放連線的時候僅僅是將連線從leased中remove掉了,並把連線放到avaliabled集合中
本著人人為我,我為人人的思想,第一次寫技術部落格,歡迎大家提出有建設性的意見。