最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用PoolingHttpClientConnectionManager實(shí)現(xiàn)http連接池過(guò)程

 更新時(shí)間:2025年11月19日 09:06:42   作者:碼上走人  
文章主要介紹了`PoolingHttpClientConnectionManager`實(shí)現(xiàn)HTTP連接池的原理、依賴(lài)實(shí)現(xiàn)、定時(shí)回收鏈接的方法,以及如何正確釋放連接以復(fù)用

PoolingHttpClientConnectionManager實(shí)現(xiàn)http連接池

PoolingHttpClientConnectionManager是通過(guò)租用連接和收回鏈接的方式來(lái)實(shí)現(xiàn)的。

解決了http請(qǐng)求的多線程問(wèn)題。

依賴(lài)

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>

實(shí)現(xiàn)

首先需要初始化連接池。設(shè)定鏈接數(shù)量等,定義清理連接池的方法,并定時(shí)調(diào)用這個(gè)方法清理無(wú)效或者長(zhǎng)期未使用的鏈接。

public class HttpClientTest {
    //全局參數(shù)
    private static PoolingHttpClientConnectionManager connectionManager = null;
    //設(shè)置請(qǐng)求參數(shù)
    private RequestConfig config;

    private CloseableHttpClient client;

    //單例模式創(chuàng)建
    private void init(){
        synchronized (HttpClientTest.class) {
            if (client == null) {
                connectionManager = new PoolingHttpClientConnectionManager();
                // http請(qǐng)求線程池,最大連接數(shù)
                int requestMaxNum = 5000;
                ConnectionConfig connConfig = ConnectionConfig.custom().setCharset(Charset.forName("utf-8")).build();
                SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(5000).build();
                connectionManager.setDefaultConnectionConfig(connConfig);
                connectionManager.setDefaultSocketConfig(socketConfig);
                // 連接池最大生成連接數(shù)
                connectionManager.setMaxTotal(requestMaxNum);
                // 默認(rèn)設(shè)置route最大連接數(shù)
                connectionManager.setDefaultMaxPerRoute(requestMaxNum);
                //設(shè)置請(qǐng)求參數(shù)
                config = RequestConfig.custom().setConnectTimeout(5000) //連接超時(shí)時(shí)間
                        .setConnectionRequestTimeout(500) //從線程池中獲取線程超時(shí)時(shí)間
                        .setSocketTimeout(5000) //設(shè)置數(shù)據(jù)超時(shí)時(shí)間
                        .build();
                // 創(chuàng)建builder
                HttpClientBuilder builder = HttpClients.custom();
                //管理器是共享的,它的生命周期將由調(diào)用者管理,并且不會(huì)關(guān)閉
                //否則可能出現(xiàn)Connection pool shut down異常
                builder.setConnectionManager(connectionManager).setConnectionManagerShared(true);
                // 長(zhǎng)連接策略
                builder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());
                // 創(chuàng)建httpClient
                client = builder.setDefaultRequestConfig(config).setRetryHandler(new MyRetryHandle()).build();
            }
        }
    }

    /**
     * 從池子中獲取連接
     * @return CloseableHttpClient
     */
    private CloseableHttpClient getClientFromHttpPool() {
        if(client == null) {
            init();
        }
        return client;
    }

}

定時(shí)回收鏈接

// 啟動(dòng)定時(shí)器,定時(shí)回收過(guò)期的連接
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
            // 關(guān)閉過(guò)期的鏈接
            connectionManager.closeExpiredConnections();
            // 選擇關(guān)閉 空閑30秒的鏈接
            connectionManager.closeIdleConnections(30, TimeUnit.SECONDS);
            }
        }, 10 * 1000, 5 * 1000);

實(shí)現(xiàn)兩個(gè)方法,執(zhí)行httpqing請(qǐng)求

public String getTest(String url) {
        CloseableHttpClient client = getClientFromHttpPool();
        HttpGet method = new HttpGet(url);
        //設(shè)置請(qǐng)求頭
        //method.setRequestHeader();
        long start = System.currentTimeMillis();
        BufferedReader reader = null;
        InputStream inputStream = null;
        StringBuilder result = new StringBuilder("");
        try {
            long startTime = System.currentTimeMillis();
            CloseableHttpResponse response = client.execute(method);
            if(response.getStatusLine().getStatusCode() == 200){
                HttpEntity httpEntity = response.getEntity();
                inputStream = httpEntity.getContent();
                //解析方式1
                reader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                    sb.append(line).append("\n");
                }
                String ret = sb.toString();
                System.out.println(ret);

                //解析方式二
                byte[] bytes = new byte[1024];
                int length = 0;
                while(-1 != (length = inputStream.read(bytes))) {
                    result.append(new String(bytes, 0, length));
                }
            }else {
                System.out.println("請(qǐng)求失敗,返回" + response.getStatusLine().getStatusCode());
            }
            System.out.println("用時(shí):" + (System.currentTimeMillis() - startTime));
            return result.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                }catch (Exception e){
                }
            }
            if(reader != null){
                try {
                reader.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            //釋放連接  
            // httpClient必須releaseConnection,但不是abort。因?yàn)閞eleaseconnection是歸還連接到到連接池,而abort是直接拋棄這個(gè)連接,而且占用連接池的數(shù)目。
            method.releaseConnection();
        }
        System.out.println("end..Duration MS:" + (System.currentTimeMillis() - start));
        return null;
    }

    public void postTest(String url, String param) {
        CloseableHttpClient client = getClientFromHttpPool();
        HttpPost method = new HttpPost(url);
        //設(shè)置請(qǐng)求頭
        //method.setRequestHeader();
        //設(shè)置請(qǐng)求參數(shù)--可以用各種方式傳入?yún)?shù)
        try {
            method.setEntity(new StringEntity(param));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        long start = System.currentTimeMillis();
        BufferedReader reader = null;
        InputStream inputStream = null;
        try {
            CloseableHttpResponse response = client.execute(method);
            if(response.getStatusLine().getStatusCode() == 200){
                HttpEntity httpEntity = response.getEntity();
                inputStream = httpEntity.getContent();
                //解析方式1
                reader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                    sb.append(line).append("\n");
                }
                String ret = sb.toString();
                System.out.println(ret);

                //解析方式二
                byte[] bytes = new byte[1024];
                int length = 0;
                StringBuilder result = new StringBuilder("");
                while(-1 != (length = inputStream.read(bytes))) {
                    result.append(new String(bytes, 0, length));
                }
                System.out.println(result);
            }else {
                System.out.println("請(qǐng)求失敗,返回" + response.getStatusLine().getStatusCode());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                }catch (Exception e){
                }
            }
            if(reader != null){
                try {
                    reader.close();
                }catch (Exception e){
                }
            }
            //關(guān)閉池子
           /* if(client != null){
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }*/
            //釋放連接
            method.releaseConnection();
        }
        System.out.println("end..Duration MS:" + (System.currentTimeMillis() - start));
    }

重試策略

加入重試策略:

// 創(chuàng)建httpClient
        return builder.setDefaultRequestConfig(config).setRetryHandler(new MyRetryHandle()).build();
/**
 * 請(qǐng)求連接池失敗重試策略
 */
public class MyRetryHandle implements HttpRequestRetryHandler {
    Logger logger = LoggerFactory.getLogger(MyRetryHandle.class);
    //請(qǐng)求失敗時(shí),進(jìn)行請(qǐng)求重試
    @Override
    public boolean retryRequest(IOException e, int i, HttpContext httpContext) {
        if (i > 3) {
            //重試超過(guò)3次,放棄請(qǐng)求
            logger.error("retry has more than 3 time, give up request");
            return false;
        }
        if (e instanceof NoHttpResponseException) {
            //服務(wù)器沒(méi)有響應(yīng),可能是服務(wù)器斷開(kāi)了連接,應(yīng)該重試
            logger.error("receive no response from server, retry");
            return true;
        }
        if (e instanceof SSLHandshakeException) {
            // SSL握手異常
            logger.error("SSL hand shake exception");
            return false;
        }
        if (e instanceof InterruptedIOException) {
            //超時(shí)
            logger.error("InterruptedIOException");
            return false;
        }
        if (e instanceof UnknownHostException) {
            // 服務(wù)器不可達(dá)
            logger.error("server host unknown");
            return false;
        }
        if (e instanceof ConnectTimeoutException) {
            // 連接超時(shí)
            logger.error("Connection Time out");
            return false;
        }
        if (e instanceof SSLException) {
            logger.error("SSLException");
            return false;
        }

        HttpClientContext context = HttpClientContext.adapt(httpContext);
        HttpRequest request = context.getRequest();
        if (!(request instanceof HttpEntityEnclosingRequest)) {
            //如果請(qǐng)求不是關(guān)閉連接的請(qǐng)求
            return true;
        }
        return false;
    }
}

原理及注意事項(xiàng)

連接池中連接都是在發(fā)起請(qǐng)求的時(shí)候建立,并且都是長(zhǎng)連接

HaoMaiClient.java中的in.close();作用就是將用完的連接釋放,下次請(qǐng)求可以復(fù)用,這里特別注意的是,如果不使用in.close();而僅僅使用response.close();結(jié)果就是連接會(huì)被關(guān)閉,并且不能被復(fù)用,這樣就失去了采用連接池的意義。

連接池釋放連接的時(shí)候,并不會(huì)直接對(duì)TCP連接的狀態(tài)有任何改變,只是維護(hù)了兩個(gè)Set,leased和avaliabled,leased代表被占用的連接集合,avaliabled代表可用的連接的集合,釋放連接的時(shí)候僅僅是將連接從leased中remove掉了,并把連接放到avaliabled集合中

http://hc.apache.org/ 文檔以及源碼

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringCloud微服務(wù)續(xù)約實(shí)現(xiàn)源碼分析詳解

    SpringCloud微服務(wù)續(xù)約實(shí)現(xiàn)源碼分析詳解

    這篇文章主要介紹了SpringCloud微服務(wù)續(xù)約實(shí)現(xiàn)源碼分析,服務(wù)續(xù)期和服務(wù)注冊(cè)非常相似,服務(wù)注冊(cè)在Eureka?Client程序啟動(dòng)之后開(kāi)啟,并同時(shí)開(kāi)啟服務(wù)續(xù)期的定時(shí)任務(wù)
    2022-11-11
  • Java面向?qū)ο蠡A(chǔ)知識(shí)之封裝,繼承,多態(tài)和抽象

    Java面向?qū)ο蠡A(chǔ)知識(shí)之封裝,繼承,多態(tài)和抽象

    這篇文章主要介紹了Java面向?qū)ο蟮姆庋b,繼承,多態(tài)和抽象,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-11-11
  • IDEA無(wú)法識(shí)別SpringBoot項(xiàng)目的簡(jiǎn)單解決辦法

    IDEA無(wú)法識(shí)別SpringBoot項(xiàng)目的簡(jiǎn)單解決辦法

    今天使用idea的時(shí)候,遇到idea無(wú)法啟動(dòng)springboot,所以這篇文章主要給大家介紹了關(guān)于IDEA無(wú)法識(shí)別SpringBoot項(xiàng)目的簡(jiǎn)單解決辦法,需要的朋友可以參考下
    2023-08-08
  • Java設(shè)計(jì)模式之策略模式示例詳解

    Java設(shè)計(jì)模式之策略模式示例詳解

    策略模式屬于Java?23種設(shè)計(jì)模式中行為模式之一,該模式定義了一系列算法,并將每個(gè)算法封裝起來(lái),使它們可以相互替換,且算法的變化不會(huì)影響使用算法的客戶(hù)。本文將通過(guò)示例詳細(xì)講解這一模式,需要的可以參考一下
    2022-08-08
  • java發(fā)送get請(qǐng)求和post請(qǐng)求示例

    java發(fā)送get請(qǐng)求和post請(qǐng)求示例

    這篇文章主要介紹了java發(fā)送get請(qǐng)求和post請(qǐng)求示例,需要的朋友可以參考下
    2014-03-03
  • PowerJob的DispatchStrategy方法工作流程源碼解讀

    PowerJob的DispatchStrategy方法工作流程源碼解讀

    這篇文章主要為大家介紹了PowerJob的DispatchStrategy方法工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Java中Servlet的生命周期詳解

    Java中Servlet的生命周期詳解

    這篇文章主要介紹了Java中Servlet的生命周期詳解,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • idea如何配置javafxsdk詳細(xì)教程

    idea如何配置javafxsdk詳細(xì)教程

    這篇文章主要介紹了idea如何配置javafxsdk,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)火鍋工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 詳解shrio的認(rèn)證(登錄)過(guò)程

    詳解shrio的認(rèn)證(登錄)過(guò)程

    這篇文章主要介紹了shrio的認(rèn)證(登錄)過(guò)程,幫助大家更好的理解和使用shrio框架,感興趣的朋友可以了解下
    2021-02-02
  • Java對(duì)象流實(shí)例代碼

    Java對(duì)象流實(shí)例代碼

    這篇文章主要介紹了Java對(duì)象流實(shí)例代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01

最新評(píng)論

大英县| 通山县| 富民县| 门源| 黄陵县| 共和县| 新巴尔虎右旗| 高雄县| 兴化市| 永济市| 舟曲县| 保亭| 北京市| 当雄县| 巨野县| 荆门市| 大埔县| 长垣县| 河北区| 普宁市| 上蔡县| 盈江县| 山阳县| 永平县| 平湖市| 德钦县| 翼城县| 随州市| 渭源县| 定陶县| 腾冲县| 孟连| 平和县| 钟山县| 新河县| 万载县| 蒙山县| 安康市| 屏边| 义马市| 乐昌市|