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

使用HTTPclient保持長連接

 更新時間:2021年10月23日 11:59:11   作者:MrHamster  
這篇文章主要介紹了使用HTTPclient保持長連接,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

HTTPclient保持長連接

首先解釋一下什么是長連接

當(dāng)我們向一臺服務(wù)器發(fā)起請求時,我們需要和對方建立一條通道,去傳輸數(shù)據(jù),所謂的短連接,就是說我們建立起了通道,然后在傳輸完數(shù)據(jù),就把通道摧毀,下次需要的時候再重新去建立通道。

長連接呢,就是指,我們建立了一條通道,傳遞完數(shù)據(jù)后,先不摧毀,下次如果還需要傳輸數(shù)據(jù),就復(fù)用這條通道。

因?yàn)橥ǖ赖慕⑹切枰ㄙM(fèi)時間的,所以長連接的優(yōu)勢就在于響應(yīng)速度快,但是服務(wù)器壓力大,因?yàn)橥瑫r有很多人在向服務(wù)器建立通道,即便有些通道已經(jīng)傳輸完數(shù)據(jù)了,由于長連接的原因,通道也不會被摧毀;短連接呢,則是,響應(yīng)速度慢,服務(wù)器壓力小。

由于現(xiàn)在更多的是強(qiáng)調(diào)用戶的體驗(yàn),所以長連接目前是最常見的。

如何在java中實(shí)現(xiàn)一個長連接呢

其實(shí)很簡單,只需要在請求的請求頭中加入特定的參數(shù) :“Connection”:"keep-alive"即可。這樣如果對方支持長連接的話,那么這個連接就會保持長連接了。

問題的關(guān)鍵就來了,在一次壓測某個https請求響應(yīng)速度的代碼中,我發(fā)現(xiàn)了,當(dāng)對方響應(yīng)數(shù)據(jù)為null,也就是responseBody中帶的數(shù)據(jù)為null時,響應(yīng)速度特別快,大概在5ms左右,但是一旦對方返回了響應(yīng)數(shù)據(jù),本次響應(yīng)就可能達(dá)到了20ms。

然后請運(yùn)維同事抓包,發(fā)現(xiàn)每次連接,都會耗費(fèi)時間在用戶認(rèn)證上,其實(shí)也就是從某個方面反應(yīng)出,每次都是新建立了一個連接。

HttpPost httpPost = new HttpPost("xxxxx");
httpPost.addHeader("Connection", "keep-alive");
CloseableHttpClient httpClient = null;
for(int i =0 ;i<5000;i++){
    long t1 = System.currentTimeMillis();
	CloseableHttpResponse response = httpClient.execute(httpPost);
	long t2 = System.currentTimeMillis();
}

上了一段簡單的代碼,表示一下大概的邏輯,實(shí)際的壓測代碼還包括了線程池,連接池的完整參數(shù)等等,如果需要的可以留言或者翻看本人的其他的博客,有寫線程池和連接池。

就是這樣一段代碼,導(dǎo)致每次連接都是新建立的連接,那么原因是什么呢,我們先上代碼:

for (int i = 0; i<5000;i++){
     long t1 = System.currentTimeMillis();
      CloseableHttpResponse response = httpClient.execute(httpPost);
      if(null != response.getEntity()){
           EntityUtils.consume(response.getEntity());
      }
      long t2 = System.currentTimeMillis();
 }

我們只需要簡單加上三行代碼,就可以解決這個問題了,這是為什么呢,讓我們點(diǎn)進(jìn)去源碼看一下

在這里插入圖片描述

這么一看, 其實(shí)這個方法也并沒有做什么,只是簡單的取到了流去關(guān)閉,為什么就保持長連接了呢。

后來仔細(xì)讀http連接的原理才得知,當(dāng)一個連接建立,響應(yīng)數(shù)據(jù)時,會封裝CloseableHttpResponse這個對象里面,其中的Entity對象就是包含著響應(yīng)體的數(shù)據(jù),我們需要用流去獲取。如果你不去獲取,那么這個數(shù)據(jù)就會存在于這個對象中,連接池就會認(rèn)為,這個通道里有未處理的數(shù)據(jù),然后它不會去復(fù)用這個通道,而是選擇重建一個通道。這就完美解釋了為什么壓測時,對方返回null時,響應(yīng)速度特別快,而攜帶返回數(shù)據(jù)時,響應(yīng)速度特別慢了。

那么再仔細(xì)想想,為什么我們平常不知道這個知識點(diǎn),卻從來沒有報過錯呢,那是因?yàn)檎G闆r下,我們都是需要會對response做處理,比如String responseContent = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); 類似這種,我們點(diǎn)進(jìn)源碼看,其實(shí)也是取到了流,并做了關(guān)閉操作。平常還是要多閱讀源碼,想想源碼。

httpclient因?yàn)楸3钟谰瞄L連接造成連接吊死的問題

httpclient使用了連接池,如果沒有設(shè)置keep-alive策略,PoolingHttpClientConnectionManager會默認(rèn)使用永久連接。

最近在調(diào)用京東api時,發(fā)現(xiàn)一個請求開始是可以獲取到數(shù)據(jù)的,但隔了兩分鐘后再請求就會出現(xiàn)read timeout異常。

對比請求成功和請求失敗的日志后發(fā)現(xiàn),請求成功的有以下日志“Connection: keep-alive”,“Connection can be kept alive indefinitely”;但請求失敗的卻打印“Shutdown connection”,“Connection discarded”。

每次失敗后再請求都會成功。因此推測中應(yīng)該是對方服務(wù)器端禁止長連接,當(dāng)連接到達(dá)一定時間會就會斷開。

后來上網(wǎng)找到keep-alive策略的代碼。

添加策略后,問題解決

ConnectionKeepAliveStrategy keepAliveStrategy = new ConnectionKeepAliveStrategy() {
            @Override
            public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
                HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
                while (it.hasNext()) {
                    HeaderElement he = it.nextElement();
                    String param = he.getName();
                    String value = he.getValue();
                    if (value != null && param.equalsIgnoreCase("timeout")) {
                        try {
                            return Long.parseLong(value) * 1000;
                        }
                        catch (NumberFormatException ignore) {
                        }
                    }
                }
                HttpHost target = (HttpHost) context.getAttribute(HttpClientContext.HTTP_TARGET_HOST);
                if ("bizapi.jd.com ".equalsIgnoreCase(target.getHostName())) {
                    return 60 * 1000;
                }
                else {
                    return 300 * 1000;
                }
   CloseableHttpClient httpClient = httpClientBuilder.setConnectionManager(pollingConnectionManager)
                .setKeepAliveStrategy(keepAliveStrategy).setDefaultRequestConfig(defaultRequestConfig).build();

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

相關(guān)文章

  • 如何用Java?幾分鐘處理完?30?億個數(shù)據(jù)(項(xiàng)目難題)

    如何用Java?幾分鐘處理完?30?億個數(shù)據(jù)(項(xiàng)目難題)

    現(xiàn)有一個 10G 文件的數(shù)據(jù),里面包含了 18-70 之間的整數(shù),分別表示 18-70 歲的人群數(shù)量統(tǒng)計,今天小編通過本文給大家講解如何用Java?幾分鐘處理完?30?億個數(shù)據(jù),這個問題一直以來是項(xiàng)目難題,今天通過本文給大家詳細(xì)介紹下,感興趣的朋友一起看看吧
    2022-07-07
  • Java項(xiàng)目中防止SQL注入的四種方案總結(jié)

    Java項(xiàng)目中防止SQL注入的四種方案總結(jié)

    SQL注入是一種代碼注入技術(shù),通過把SQL命令插入到Web表單遞交或輸入域名或頁面請求的查詢字符串,最終達(dá)到欺騙服務(wù)器執(zhí)行惡意的SQL命令,下面我們就來看看如何在項(xiàng)目中防止SQL注入吧
    2023-10-10
  • Java Map 按Key排序?qū)嵗a

    Java Map 按Key排序?qū)嵗a

    這篇文章主要介紹了Java Map 按Key排序?qū)嵗a的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • java中brew安裝rabbitmq以及簡單實(shí)例

    java中brew安裝rabbitmq以及簡單實(shí)例

    RabbitMQ是基于AMQP協(xié)議,由Erlang語言開發(fā)的開源消息隊(duì)列系統(tǒng),廣泛應(yīng)用于分布式系統(tǒng)中,用于應(yīng)用程序間的消息傳遞,它支持多種交換機(jī)類型,如直連交換機(jī)、扇形交換機(jī)和主題交換機(jī)等,能夠滿足不同的消息路由需求
    2024-10-10
  • Java新手教程之ArrayList的基本使用

    Java新手教程之ArrayList的基本使用

    ArrayList就是傳說中的動態(tài)數(shù)組,用MSDN中的說法,就是Array的復(fù)雜版本,這篇文章主要給大家介紹了關(guān)于Java新手教程之ArrayList基本使用的相關(guān)資料
    2021-06-06
  • 一篇文章帶你了解JAVA結(jié)構(gòu)化編程詳情

    一篇文章帶你了解JAVA結(jié)構(gòu)化編程詳情

    下面小編就為大家?guī)硪黄v解JAVA結(jié)構(gòu)化編程的文章。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-09-09
  • Springboot發(fā)送郵件功能的實(shí)現(xiàn)詳解

    Springboot發(fā)送郵件功能的實(shí)現(xiàn)詳解

    電子郵件是—種用電子手段提供信息交換的通信方式,是互聯(lián)網(wǎng)應(yīng)用最廣的服務(wù)。本文詳細(xì)為大家介紹了SpringBoot實(shí)現(xiàn)發(fā)送電子郵件功能的示例代碼,需要的可以參考一下
    2022-09-09
  • struts2配置靜態(tài)資源代碼詳解

    struts2配置靜態(tài)資源代碼詳解

    這篇文章主要介紹了struts2配置靜態(tài)資源的相關(guān)內(nèi)容,文中涉及了具體代碼介紹,需要的朋友可以參考下。
    2017-09-09
  • 關(guān)于連接遠(yuǎn)程redis的流程

    關(guān)于連接遠(yuǎn)程redis的流程

    這篇文章主要介紹了關(guān)于連接遠(yuǎn)程redis的流程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • JavaCV簡介與環(huán)境搭建詳細(xì)步驟

    JavaCV簡介與環(huán)境搭建詳細(xì)步驟

    JavaCV是一個開源的Java接口,它為幾個著名的計算機(jī)視覺庫(如OpenCV、FFmpeg)提供了Java封裝,這篇文章主要給大家介紹了關(guān)于JavaCV簡介與環(huán)境搭建的相關(guān)資料,需要的朋友可以參考下
    2024-04-04

最新評論

抚顺县| 监利县| 普陀区| 长岭县| 高台县| 墨脱县| 青阳县| 涪陵区| 兰溪市| 临沭县| 宕昌县| 广饶县| 桂东县| 醴陵市| 博客| 鲁山县| 香格里拉县| 万全县| 仙游县| 萝北县| 颍上县| 包头市| 织金县| 邓州市| 慈利县| 增城市| 哈密市| 芷江| 海林市| 简阳市| 汝南县| 观塘区| 晋州市| 临清市| 句容市| 贵定县| 万载县| 屯门区| 西丰县| 南丰县| 横峰县|