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集合中
本着人人為我,我為人人的思想,第一次寫技術博客,歡迎大家提出有建設性的意見。