HTTP長鏈接--Keep-Alive

1、HTTP/1.0css

HTTP1.0版本的Keep-alive並不像HTTP1.1那樣是默認發送的,因此要想鏈接獲得保持,必須手動配置發送connection:keep-alive字段。若想斷開keep-alive鏈接,需發送Connection:close字段html

注意:這裏的鏈接是HTTP依賴的傳輸協議TCP,而不是HTTP自己。瀏覽器

爲何須要長鏈接?服務器

長鏈接能夠提升鏈接的利用效率,即HTTP能夠複用一條鏈接。例如某個用戶瀏覽一個網站,他很長一段時間才跳轉到另外一個連接,彷佛保持長鏈接沒有什麼好處,很浪費資源。網絡

但若是這個網站的併發量很大,保持長鏈接的好處就凸顯了。若是每一個請求都須要創建新的TCP鏈接,那對服務器的開銷是至關的。併發

 

創建鏈接報文首部格式:性能

Connection:Keep-Alive網站

Keep-Alive:timeout ; max       #參數之間用;分號隔開設計

參數:max 最大處理事務數量代理

      timeout 鏈接保持的時間,單位爲秒

 

斷開鏈接報文首部格式:

Connection:close

 

Keep-Alive的創建過程

客戶端向服務器在發送請求報文同時在首部添加發送Connection字段》服務器收到請求並處理connection字段》服務器回送Connection:Keep-Alive字段給客戶端》客戶端接收到connection字段》Keep-Alive鏈接創建成功

 

服務端自動斷開過程:

客戶端向服務器只是發送內容報文(不包含Connection字段)》服務器收到請求並處理》服務器返回客戶端請求的資源並關閉鏈接》客戶端接收資源,發現沒有Connection字段,斷開鏈接

 

客戶端請求斷開鏈接過程:

客戶端向服務器發送Connection:close字段》服務器收到請求並處理connection字段》服務器回送響應資源並斷開鏈接》客戶端接收資源並斷開鏈接

 

事務:

在基於TCP鏈接的http協議中,一個事務表示客戶端向服務端請求一個資源並獲得響應返回的過程。這個資源多是html,css,js文件。

 

例如:

 

表示鏈接的最大處理事務數是5,鏈接時間是2分鐘

 

Keep-Alive的限制和規則

(1)事務處理的接收端必須接收到發送端發送的正確的Content-Length字段,或者接收到MIME多部件多媒體類型(容許鏈接屢次發送不一樣類型的資源)字段或者接收到Chunked分塊模式字段。以客戶端向服務端發送資源爲例(實際上,在一條HTTP信道上,數據傳輸是雙向的,這裏只是其中一種情形來說述)。在一個非Keep—Alive的鏈接中,每一次資源請求都須要建立一個HTTP鏈接,出錯了重傳不會擔憂先後兩次的Content-Length不相同問題。而若是是在Keep-Alive鏈接中,問題就沒有那麼簡單了。想象一下出錯客戶端須要從新發送資源給服務端,而此時服務端端保存的可能仍是上一條錯誤報文的Content-Length(多是0),那麼在接收新資源時候就會出現實體內容長度和content-length不一致等問題(這裏存在了太多的細節問題)。

(2)不該該與沒法肯定是否支持Connection首部的代理服務器創建keep-alive鏈接,以防止出現下面要介紹的啞代理問題。但實際應用中,這一點不是老是能作到。

 

啞代理問題

盲中繼指的是一些自身沒有處理Connection:Keep-Alive的能力代理服務器。當客戶端向服務端發送Connection字段的時候,經過代理服務器,而代理服務器沒有處理Connection字段,而只將其當一個擴展首部來處理,將報文原本來本發送給服務端,服務端接收到Connecton字段後回送Connection字段。這時代理服務器仍是原封不動將報文轉送給客戶端。此時客戶端和服務器都創建了Keep-Alive鏈接,而代理服務器卻絕不知情。它一直在等待客戶端給它發送斷開鏈接的字段,由於一個事務已經完成,已經沒有必要保持鏈接了。這是創建了Keep-Alive鏈接客戶端繼續互相發送數據,而代理服務器收到的不是Connection:close字段,因此對此就會視而不見,就像‘盲’了同樣。

根據《HTTP權威指南》中的描述,目前瀏覽器解決啞代理問題的一個解決方案使擴展首部字段Proxy-Connection,是由Netscape提出的。大體的實現原理是,客戶端服務器會向代理服務器發送Proxy-Connection字段,若是對方是聰明的代理,它就會用Connection代替Proxy-Connection字段,發送給服務端,服務端接受到Connection字段以後就知道是要創建持久鏈接,這樣客戶端,代理,服務端三者都會明白鬚要創建一個持久鏈接。而若是對方是一個盲中繼,它就會直接把Proxy-Connection當作擴展首部直接轉發給服務端,服務端接收到後發現是Proxy-Connection字段,會自動忽略,也就是說不會創建持久鏈接,一般接下來事務完成以後就是直接關閉鏈接了。這樣就不會產生上文所述的問題。

因爲本人對這方面知識還接觸比較少,在這裏就不對Proxy-Connection做更深刻闡述了。

 

 

2、HTTP/1.1

客戶端(瀏覽器)若是使用的是HTTP/1.1版本,默認會發送connection:keep alive字段

,若是沒有特殊說明,TCP鏈接是默認保持的,而須要將一個鏈接關閉,則須要客戶端發送Connection:close首部字段。

HTTP1.1通過版本的更迭,HTTP1.1逐漸中止了對Keep-alive鏈接的支持,用一種名爲持久鏈接(persistent connection)的改進型機制設計取代了它。這種機制默認鏈接創建以後是持久的,也就是說客戶端不須要依靠首部添加Keep-alive字段來保持鏈接。在但願斷開鏈接的時候,則須要客戶端首部添加Connection:close字段。

 

持久鏈接的限制和規則:

(1)HTTP/1.1對代理服務器的要求更高,它必須能管理與客戶端和服務端之間的持久鏈接。

(2)因爲HTTP/1.1設備隨時可能斷開鏈接(由於出錯;或者是鏈接空閒一段時間後,服務端作了邏輯處理,主動關閉;也多是其餘緣由),客戶端可能在沒有接收到整條完整的響應,服務端就斷開了鏈接。因此客戶隨時要作好從新發送請求的準備。

(3)一個用戶客戶端對任何服務器或者代理最多隻能維持兩條持久鏈接,以防止服務器過載。因此做爲中間者身份的代理服務器可能須要更多到服務器的鏈接來支持併發的用戶請求。例若有N個用戶請求不一樣的服務器,代理須要維護2N條到任意服務器或者父代理的鏈接。

 

管道化鏈接

HTTP/1.1容許在持久鏈接的基礎上自由選擇使用請求管道。管道的原理很像隊列。在響應到達前,客戶端發送的請求能夠放進管道里面,當第一條請求發送到服務端而還客戶端尚未接收到響應的時候,後面的請求能夠接着發送了。爲何能夠這樣?這就是管道的做用了,由於管道中的請求是‘提早準備好的’,它無需等待客戶端判斷已經接收到響應了再發送新的請求(這是非管道鏈接的串行請求)。在高時延的網絡中,管道化鏈接有利於下降網絡的環回時間,提升網絡傳輸性能。

雖然管道化鏈接有它強大的優點,可是管道化鏈接也有它的侷限性。

1)客戶端的請求在管道中是有必定次序的。但因爲HTTP報文是沒有順序,響應報文一旦次序出錯,就沒法與請求一一對應匹配起來。

2)通常來講,非冪等性(例如POST請求,下文會講述)請求是不但願放進管道的。緣由是,管道傳輸中若是出現了錯誤,請求和響應的次序沒法獲得保障,在一些訂單或者涉及資金的POST提交中,結果是災難性的。

    3)在管道傳輸過程當中,服務器關閉了鏈接,這時有許多沒有完成的請求事務,那麼客戶端和服務端採起什麼機制來確認已經處理和沒有處理的事務這一問題值得商榷。客戶端可能必須從新發送請求鏈接而且從新發送全部的管道中的請求。

 

 

3、重試和冪等性

當事務由於一條持續的鏈接的意外關閉而被終端,客戶端須要從新發送請求。這種重試在管道化鏈接中更復雜。

一次HTTP請求的類型多是GET , POST , HEAD , PUT , DELETE , TRACE , OPTION,若是重試先後對服務端的數據沒有很大影響的請求類型就是冪等性的。顯然,POST是非冪等的。關於冪等性的更多討論,能夠看看這篇文章:https://www.jianshu.com/p/178da1e2903c

 

 

4、最後,關於鏈接的關閉:

何時控制性地關閉鏈接,以及如何關閉鏈接,以達到信道上最高效率的數據傳輸是一個值得研究和討論的問題。《HTTP權威指南》中也沒有提供一些可行的方案。之後有接觸到相關知識,我會繼續補充。

 

 

參考文章:https://www.jianshu.com/p/178da1e2903c

相關文章
相關標籤/搜索