關於HTTP /1.1 與 /2.0版本的常見差異和特性

zekun發表於2018-09-22

HTTP 1.1

  • 預設使用長連線(connection:keep-alive)。解決了複用TCP的問題,可以減少TCP的三次握手開銷。
    • 指的是用同一個TCP連線來傳送和接受多個http請求/應答,而不是為了每一個新的請求/應答開啟新的TCP連線的方法。
      • 另一個定義:一定時間內,同一域名多次請求資料,只建立一次HTTP請求,其他請求可複用每一次建立的連線通道,以達到提高請求效率的問題。這裡面所說的一定時間是可以配置的,不管你用的是Apache還是nginx
      • 但是還是存在效率問題(HTTP2.0通過多路複用解決)
        • 序列的檔案傳輸,只能順序傳輸:當請求a檔案時,b檔案只能等待,等待a連線到伺服器、伺服器處理檔案、伺服器返回檔案,這三個步驟。我們假設這三步用時都是1秒,那麼a檔案用時為3秒,b檔案傳輸完成用時為6秒,依此類推。(注:此項計算有一個前提條件,就是瀏覽器和伺服器是單通道傳輸)
        • 連線數上限:我們假設Apache設定了最大併發數為300,因為瀏覽器限制,瀏覽器發起的最大請求數為6,也就是伺服器能承載的最高併發為50,當第51個人訪問時,就需要等待前面某個請求處理完成。
    • 支援只傳送header資訊而不帶任何body資訊,如果客戶端有許可權,則返回100(代表繼續),否則返回401(無許可權)客戶端如果接收到100,才把請求的Body傳送到伺服器。
      • 這樣當伺服器返回401的時候,客戶端就可以不用傳送請求body了,節約了頻寬
    • 1.1開始支援獲取檔案的部分內容,這支援了 並行下載 和 斷點續傳。通過在Header的兩個引數實現
      • 客戶端請求的時候傳送Range引數, 指定第一個位元組的位置和最後一個位元組的位置
      • 服務端響應的引數是:Content-Range
      • 在實際場景中,會出現一種情況,即在終端發起續傳請求時,URL 對應的檔案內容在伺服器端已經發生變化,此時續傳的資料肯定是錯誤的。如何解決這個問題 ? -用Last-modified / etag / if-range
        • If-Range 必須與 Range 配套使用。如果請求報文中沒有 Range,那麼 If-Range 就會被忽略。如果伺服器不支援 If-Range,那麼 Range 也會被忽略。
      • 工作原理:
        • 第一次請求,客戶端發起一個get請求;伺服器處理請求,返回檔案內容以及相應的Header,包括Etag
        • 第二次請求(斷點續傳):客戶端發起get請求,同時傳送if-range,這個if-range的值就是第一次請求中伺服器返回的etag;伺服器判斷etag是否匹配,是則返回206,否則返回200
    • HTTP/1.1 引入了更多的快取控制策略,比如i
      • if-unmodified-since,其實就是和if-modified-since差不多的,常用來做判斷斷點續傳的檔案是否被修改過了。如果沒有被修改,返回200;否則返回412預處理錯誤。
      • if-match
      • if-none-match
    • 1.1開始有Host(域) 這個概念

HTTP 2.0

  • 最大的一個目標是在使用者和網站間只用一個連線

  • 二進位制分幀(Binary Framing)

  • http1.x誕生的時候是明文協議,其格式由三部分組成:start line(request line或者status line),header,body。要識別這3部分就要做協議解析,http1.x的解析是基於文字。基於文字協議的格式解析存在天然缺陷,文字的表現形式有多樣性,要做到健壯性考慮的場景必然很多,二進位制則不同,只認0和1的組合。基於這種考慮http2.0的協議解析決定採用二進位制格式,實現方便且健壯

  • 幾個概念:

    • frame 幀:http/2通訊的最小單位,單個幀包含幀首部,其中標註了當前幀所屬的stream
    • message 訊息:由若干個frame組合而成,例如請求,響應
    • connection 連線:與http/1 相同,指的都是對應的tcp連線
    • stream 流,已建立的連線上的雙向位元組流。
    • 資料流以訊息的形式傳送,而訊息由一個或多個幀組成,幀可以在資料流上亂序傳送,然後再根據每個幀首部的流識別符號重新組裝。二進位制分幀是HTTP/2的基石,其他優化都是在這一基礎上來實現的。
  • 支援多路複用(Multiplexing),在資料鏈路層使用二進位制分幀,可以允許同時通過單一的ht2連線發起多重的請求-響應訊息,同個域名只需要佔用一個 TCP 連線,解決了請求阻塞的問題。

    • 在HTTP1.1中,同一域名在同一時間的請求數量是有限制的,超過限制會阻塞請求。
    • Head-of-Line Blocking,在http1.x中,TCP的connection在同一時間只能允許一個請求經過,因為HTTP1.x需要每條請求都是可是識別,按順序傳送,否則server就無法判斷該相應哪個具體的請求。
    • 多路複用指的是:在同一個域名下,開啟一個TCP的connection,每個請求以stream的方式傳輸,每個stream有唯一標識,connection一旦建立,後續的請求都可以複用這個connection並且可以同時傳送,server端可以根據stream的唯一標識來相應對應的請求。之所以可以複用,是因為每個stream高度獨立,堵塞的stream不會影響其它stream的處理。一個連線上可以有多個stream,每個stream的frame可以隨機的混雜在一起,接收方可以根據stream id將frame再歸屬到各自不同的request裡面。
    • 而多路複用什麼時候關閉呢?
      • 使用者離開這個頁面
      • server主動關閉connection
    • 那麼在HTTP2.0下,我們就不需要做
      • JS檔案的合併:在之前,我們會將上線若干個模組的程式碼進行壓縮合併成一個檔案,減少http請求數。但是這樣就會導致快取問題:如果有一個模組修改了,就會導致客戶端重新下載整個大檔案,難以快取。現在用HTTP2.0就不需要做這件事情了
      • CDN資源放在不同域名下,繞開瀏覽器的通道上限。
  • 頭部壓縮:

    • http2.0使用encoder來減少需要傳輸的header大小,通訊雙方各自cache一份header fields表,既避免了重複header的傳輸,又減小了需要傳輸的大小。高效的壓縮演算法可以很大的壓縮header,減少傳送包的數量從而降低延遲。
  • 服務端推送(server push):

    • 從HTTP/2開始,伺服器除了相應客戶端的請求之外,還可以向客戶端額外推送資源,這些資源遵守同源協議,有自己獨立的URL,可以被瀏覽器快取,可以多頁面共享;同時客戶端還可以拒絕推送過來的資源
    • 有了server push,客戶端可以通過額外的http頭部,列出需要伺服器push 哪些資源
    • 伺服器可以提前向客戶端推送需要的資源。
  • 流量控制(flow control):

    • 在TCP的流量控制中,是以單個tcp為單位的流量控制;可是在http2.0時代,傳輸已經以單個stream為單位,tcp的流量控制無法做到這麼精細的粒度,因此就在應用層引入了flow control,從而對每一個stream都做了不同的限流
    • 而HTTP/2利用stream來實現flow-control,引入了stream對TCP連線的搶佔,不加控制就會造成stream被阻塞。而http/2上的flow-control就是確保同一連線上的多個流之間不會造成破壞性的干擾
  • 流優先順序(stream priority):

    • 在HTTP/2中,每個請求都可以帶一個31bit的優先值,0表示最高優先順序, 數值越大優先順序越低。有了這個優先值,客戶端和伺服器就可以在處理不同的流時採取不同的策略,以最優的方式傳送流、訊息和幀。(其實我的理解還是為了解決TCP搶佔的問題?)

從HTTP/1.x到HTTP/2的過程中,仍然適用的優化規則

  • 減少DNS查詢。DNS查詢需要時間,沒有resolved的域名會阻塞請求。
  • 減少TCP連線。HTTP/2只使用一個TCP連線。
  • 使用CDN。使用CDN分發資源可以減少延遲。
  • 減少HTTP跳轉。特別是非同一域名的跳轉,需要DNS,TCP,HTTP三種開銷。
  • 消除不必要的請求資料。HTTP/2壓縮了Header。
  • 壓縮傳輸的資料。gzip壓縮很高效。
  • 客戶端快取資源。快取是必要的。
  • 消除不必要的資源。激進的提前獲取資源對客戶端和服務端都開銷巨大。

因為HTTP/2而不一樣的優化規則

  • 域名分片:大概意思就是我們把資源放在不同域名下,繞過瀏覽器HTTP連線數的限制。HTTP2.0不用了
  • 檔案合併:在HTTP2.0中,我們要使用更小的模組,優化快取策略(因為大檔案的某一部分更改了,整個大檔案就無法快取了)
  • 內聯資源:在HTTP2.0中直接使用server push。

參考資料:

  1. github.com/creeperyang…
  2. 關於http2.0中的流量控制:www.zhihu.com/question/27…
  3. www.cnblogs.com/memset/p/ht…

相關文章