1. 程式人生 > >HttpClient4.5.2 連線池原理及注意事項

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集合

本著人人為我,我為人人的思想,第一次寫技術部落格,歡迎大家提出有建設性的意見。