一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 使用HTTPclient保持長連接

使用HTTPclient保持長連接

2022-02-26 00:42MrHamster Java教程

這篇文章主要介紹了使用HTTPclient保持長連接,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

HTTPclient保持長連接

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

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

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

因為通道的建立是需要花費時間的,所以長連接的優勢就在于響應速度快,但是服務器壓力大,因為同時有很多人在向服務器建立通道,即便有些通道已經傳輸完數據了,由于長連接的原因,通道也不會被摧毀;短連接呢,則是,響應速度慢,服務器壓力小。

由于現在更多的是強調用戶的體驗,所以長連接目前是最常見的。

如何在java中實現一個長連接呢

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

問題的關鍵就來了,在一次壓測某個https請求響應速度的代碼中,我發現了,當對方響應數據為null,也就是responseBody中帶的數據為null時,響應速度特別快,大概在5ms左右,但是一旦對方返回了響應數據,本次響應就可能達到了20ms。

然后請運維同事抓包,發現每次連接,都會耗費時間在用戶認證上,其實也就是從某個方面反應出,每次都是新建立了一個連接。

?
1
2
3
4
5
6
7
8
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();
}

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

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

?
1
2
3
4
5
6
7
8
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();
 }

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

使用HTTPclient保持長連接

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

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

那么再仔細想想,為什么我們平常不知道這個知識點,卻從來沒有報過錯呢,那是因為正常情況下,我們都是需要會對response做處理,比如String responseContent = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); 類似這種,我們點進源碼看,其實也是取到了流,并做了關閉操作。平常還是要多閱讀源碼,想想源碼。

httpclient因為保持永久長連接造成連接吊死的問題

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

最近在調用京東api時,發現一個請求開始是可以獲取到數據的,但隔了兩分鐘后再請求就會出現read timeout異常。

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

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

后來上網找到keep-alive策略的代碼。

添加策略后,問題解決

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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();

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/MrHamster/article/details/94590184

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: jizzjizz大学生 | julianann办公室 | 女教师系列三上悠亚在线观看 | 国产高清在线视频一区二区三区 | 青青草视频破解版 | 四虎影院免费在线 | 日韩香蕉视频 | 久久这里只有精品视频e | 成人1234 | tube8最近日本护士 | 欧美成年黄网站色高清视频 | 公翁的舌尖研磨她的花蒂小说 | 欧美不卡一区二区三区免 | 国内精品一区二区三区东京 | 欧美精品一区二区三区免费 | 欧美视频在线一区 | 国产亚洲一欧美一区二区三区 | 亚洲大尺码 | 九色PORNY丨视频入口 | 亚洲欧美在线免费 | 亚洲玖玖| 天堂网在线.www天堂在线资源 | 精品久久日日躁夜夜躁AV | 国产盗摄女厕美女嘘嘘 | 国产999在线观看 | 特黄aa级毛片免费视频播放 | 国产精品边做边接电话在线观看 | 色噜噜视频影院 | 操美女骚b | 日本韩国无矿砖码 | 甜性涩爱| 好大好硬好长好爽a网站 | 狠狠色婷婷丁香六月 | 催眠 迷j系列小说 | 欧美精品一区视频 | 91精品啪在线观看国产91九色 | 白丝超短裙被输出娇喘不停小说 | 4hu永久地域网名入口 | 99久久国语露脸精品国产 | 亚洲品质自拍视频网站 | 袖珍人与大黑人性视频 |