HTTP發展的根本原因----連接無法複用和head of line blocking

HTTP發展的根本原因----連接無法複用和head of line blocking

HTTP發展的根本原因

HTTP優化的2個主要因素是帶寬和延遲,其中隨着網絡的發展,帶寬基本可以滿足,那核心問題就轉變爲如何降低延遲. 根據HTTP1.0可以發現,影響延遲的2個關鍵在於連接無法複用head of line blocking.

  • 連接無法複用: 會導致每次請求都經歷三次握手和慢啓動。三次握手在高延遲的場景下影響較明顯,慢啓動則對文件大批量請求影響較大。
  • head of line blocking: 會導致帶寬無法被充分利用,以及後續健康請求被阻塞。假設有5個請求同時發出,對於HTTP1.0的實現, 在第一個請求沒有收到回覆之前,後續從應用層發出的請求只能排隊,請求2,3,4,5只能等請求1的response回來之後才能逐個發出。網絡通暢的時候性能影響不大,一旦請求1的request因爲什麼原因沒有抵達服務器,或者response因爲網絡阻塞沒有及時返回,影響的就是所有後續請求,問題就變得比較嚴重了。

    ii

1. 解決連接無法複用問題

  • http1.0協議頭裏可以設置Connection:Keep-Alive。在header裏設置Keep-Alive可以在一定時間內複用連接,具體複用時間的長短可以由服務器控制,一般在15s左右。到http1.1之後, Connection的默認值就是Keep-Alive,如果要關閉連接複用需要顯式的設置Connection:Close。一段時間內的連接複用對PC端瀏覽器的體驗幫助很大,因爲大部分的請求在集中在一小段時間以內。但對移動app來說,成效不大,app端的請求比較分散且時間跨度相對較大。所以移動端app一般會從應用層尋求其它解決方案.
  • 方案一:基於tcp的長鏈接: 現在越來越多的移動端app都會建立一條自己的長鏈接通道,通道的實現是基於tcp協議。基於tcp的socket編程技術難度相對複雜很多,而且需要自己制定協議,但帶來的回報也很大。信息的上報和推送變得更及時,在請求量爆發的時間點還能減輕服務器壓力(http短連接模式會頻繁的創建和銷燬連接)。不止是IM app有這樣的通道,像淘寶這類電商類app都有自己的專屬長連接通道了。現在業界也有不少成熟的方案可供選擇了,google的protobuf就是其中之一。
  • 方案二:http long-polling: long-polling可以用下圖表示:客戶端在初始狀態就會發送一個polling請求到服務器,服務器並不會馬上返回業務數據,而是等待有新的業務數據產生的時候再返回。所以連接會一直被保持,一旦結束馬上又會發起一個新的polling請求,如此反覆,所以一直會有一個連接被保持。服務器有新的內容產生的時候,並不需要等待客戶端建立一個新的連接。缺點是: long-polling在用戶增長的時候極大的增加服務器壓力;polling的方式穩定性並不好,需要做好數據可靠性的保證,比如重發和ack機制。polling的response有可能會被中間代理cache住,要處理好業務數據的過期機制。long-polling方式還有一些缺點是無法克服的,比如每次新的請求都會帶上重複的header信息,還有數據通道是單向的,主動權掌握在server這邊,客戶端有新的業務請求的時候無法及時傳送。
ii
  • 方案三:http streaming: http streaming流程大致如下:同long-polling不同的是,server並不會結束初始的streaming請求,而是持續的通過這個通道返回最新的業務數據。顯然這個數據通道也是單向的。streaming是通過在server response的頭部裏增加”Transfer Encoding: chunked”來告訴客戶端後續還會有新的數據到來。除了和long-polling相同的難點之外,streaming還有幾個缺點:有些代理服務器會等待服務器的response結束之後纔會將結果推送到請求客戶端。對於streaming這種永遠不會結束的方式來說,客戶端就會一直處於等待response的過程中。業務數據無法按照請求來做分割,所以客戶端沒收到一塊數據都需要自己做協議解析,也就是說要做自己的協議定製。streaming不會產生重複的header數據。
ii
  • 方案四:web socket: WebSocket和傳統的tcp socket連接相似,也是基於tcp協議,提供雙向的數據通道。WebSocket優勢在於提供了message的概念,比基於字節流的tcp socket使用更簡單,同時又提供了傳統的http所缺少的長連接功能。不過WebSocket相對較新,2010年才起草,並不是所有的瀏覽器都提供了支持。各大瀏覽器廠商最新的版本都提供了支持。

2. 解決head of line blocking問題

HTTP1.1和HTTP2.0的最大優勢就是對於頭部阻塞問題的解決.

  • HTTP1.1的解決方案 ---- http pipelining: 和圖一相比最大的差別是,請求2,3不用等請求1的response返回之後才發出,而是幾乎在同一時間把request發向了服務器。2,3及所有後續共用該連接的請求節約了等待的時間,極大的降低了整體延遲。缺點: pipelining只能適用於http1.1,一般來說,支持http1.1的server都要求支持pipelining。 只有冪等的請求(GET,HEAD)能使用pipelining,非冪等請求比如POST不能使用,因爲請求之間可能會存在先後依賴關係。head of line blocking並沒有完全得到解決,server的response還是要求依次返回,遵循FIFO(first in first out)原則。絕大部分的http代理服務器不支持pipelining。和不支持pipelining的老服務器協商有問題。可能會導致新的Front of queue blocking問題。正是因爲有這麼多的問題,各大瀏覽器廠商要麼是根本就不支持pipelining,要麼就是默認關掉了pipelining機制,而且啓用的條件十分苛刻。
ii
  • HTTP2.0的解決方案 ---- 多路複用multiplexing, 請求優先級request prioritization, 首部壓縮header packet,服務器推送server push HTTP2.0的目標在一開始就是瞄準http1.x的痛點,即延遲和安全性。我們上面通篇都在討論延遲,至於安全性,由於http是明文協議,其安全性也一直被業界詬病,不過這是另一個大的話題。如果以降低延遲爲目標,應用層的http和傳輸層的tcp都是都有調整的空間,不過tcp作爲更底層協議存在已達數十年之久,其實現已深植全球的網絡基礎設施當中,如果要動必然傷經動骨,業界響應度必然不高,所以HTTP2.0的手術刀對準的是http。降低延遲,客戶端的單連接單請求,server的FIFO響應隊列都是延遲的大頭。http最初設計都是客戶端發起請求,然後server響應,server無法主動push內容到客戶端。壓縮http header,http1.x的header越來越膨脹,cookie和user agent很容易讓header的size增至1kb大小,甚至更多。而且由於http的無狀態特性,header必須每次request都重複攜帶,很浪費流量。
    爲了增加業界響應的可能性,聰明的google一開始就避開了從傳輸層動手,而且打算利用開源社區的力量以提高擴散的力度,對於協議使用者來說,也只需要在請求的header裏設置user agent,然後在server端做好支持即可,極大的降低了部署的難度。
ii

相關鏈接

[1] HTTP 0.9 HTTP 1.0 HTTP 1.1 HTTP 2.0區別
[2] http2.0深入理解
[3] HTTP 2.0 協議詳解
[4] http2.0
[5] HTTP1.0、HTTP1.1 和 HTTP2.0 的區別

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章