httpclient 連接池測試


為什么需要使用http連接池

1、降低延遲:如果不采用連接池,每次連接發起Http請求的時候都會重新建立TCP連接(經歷3次握手),用完就會關閉連接(4次揮手),如果采用連接池則減少了這部分時間損耗,別小看這幾次握手,本人經過測試發現,基本上3倍的時間延遲

2、支持更大的並發:如果不采用連接池,每次連接都會打開一個端口,在大並發的情況下系統的端口資源很快就會被用完,導致無法建立新的連接

 

連接池實例

連接池管理器代碼

import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import java.security.NoSuchAlgorithmException;

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;
    }
}

使用連接池代碼

private static CloseableHttpClient getHttpClient(){
        HttpConnectionManager httpConnectionManager= (HttpConnectionManager) AppBeanUtil.getBean("httpConnectionManager");
        return  httpConnectionManager.getHttpClient();
    }

獲取連接

public static String getFromUrl(String url, Map<String, String> params,String charset) throws Exception {
        if(StringUtil.isEmpty(charset)){
            charset=defaultCharset;
        }
        CloseableHttpClient httpclient = getHttpClient();
        URIBuilder uriBuilder = new URIBuilder(url);
        uriBuilder.setCharset(Charset.forName(charset));
        if(params!=null){
            Iterator<String> keyIt = params.keySet().iterator();
            while (keyIt.hasNext()) {
                String key = keyIt.next();
                String val = params.get(key);
                uriBuilder.setParameter(key, val);
            }
        }
        URI uri = uriBuilder.build();

        HttpGet httpget = new HttpGet(uri);

        CloseableHttpResponse response = httpclient.execute(httpget);
        try {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String content=getContent(entity.getContent());
                return content;
            }
        } finally {
            response.close();
        }
        return null;
    }

訪問url 獲取內容

private static String getContent(InputStream instream) throws IOException {
        StringWriter writer = new StringWriter();
        IOUtils.copy(instream, writer, defaultCharset);
        instream.close();
        return writer.toString();
    }

讀取數據,這里 instream 需要進行關閉。

測試連接池和不使用連接池的效率測試。

@Test
    public void postTest() throws Exception {

        long start=System.currentTimeMillis();
        for (int i = 0; i < 200; i++) {
            String content=HttpClientPoolUtil.postFromUrl("https://www.cnblogs.com/kingszelda/p/8988505.html",new HashMap<>());
        }
        System.err.println("---------------------------postTest---------------------------");
        System.err.println(System.currentTimeMillis()-start);

        System.err.println("---------------------------postTest---------------------------");
        start=System.currentTimeMillis();
        for (int i = 0; i < 200; i++) {
            String content= HttpClientUtil.postFromUrl("https://www.cnblogs.com/kingszelda/p/8988505.html",new HashMap<>());
        }
        System.err.println(System.currentTimeMillis()-start);


    }

測試結果

---------------------------postTest---------------------------
9791
---------------------------postTest---------------------------
39427

可以看到在使用連接池訪問兩百次花費時間為 9.7秒,不使用連接池為 39.4秒,時間相差為30秒。

通過計算從發送請求到接收請求約花48毫秒,每建立一次連接需要花費的時間為150毫秒,可見創建連接是需要非常消耗性能的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM