記錄 http2 四個難以理解的疑惑點

momo707577045發表於2022-03-04

文章基調

  • 不是科普類文章,不是科普 http2 功能的文章
  • 記錄 http2 中難以理解的點,系作者在學習 http2 時的困惑,已經最終的理解
  • 是個人的理解,可能有不嚴謹的地方,歡迎討論

    如何理解 TCP 分幀 與 http2 分幀 的區別

  • 假設「傳輸完整的資料」是「運輸一個訂單貨物」,每「訂單中的一個貨物」佔滿「一個貨車廂」
  • TCP 位於傳輸層,可以理解為運輸的貨車

    • TCP 中的每一幀都是有序的,按發車時間標記趟次,第一趟次,第二趟次,第三趟次,第 N 趟次
    • TCP 可以同時發若干輛車,假設 4 輛車,則一次發車就有,第一趟次,第二趟次,第三趟次,第四趟次
    • 每輛車有些提前到達,有些很慢才到,不一定按照發車的順序到達目的地
    • 當其中一個趟次的車回來了,才發下一趟車次。
    • 趟次的作用,是為了貨品送到目的地的時候可以重新按順序排列,可以將每趟次的貨理解為高達模型的零件(一車只運送一個零件),有順序,才能識別重新拼裝起來
    • 將一個訂單中的貨,分別通過不同的趟次運輸,就是「TCP 二進位制分幀」,將訂單的貨(完整的資料)分成每一車(幀)進行運輸
  • HTTP 處於應用層,一個 http 請求及響應,可以理解為下訂單(請求)購買一批貨(響應)的過程,(注意是一批,有若干個貨物)而這批貨並沒有貨品名稱(無法對應這批貨對應的是哪個訂單,無法將響應與請求關聯起來

    • 這時 http 還沒有分幀化,粒度是以訂單為單位,一個訂單就是一個 http
  • 將一個 TCP 連結理解為一個運輸合同

  • http0.9,1.0
    【問題】每一次訂單都籤一次運輸合同,很麻煩

    • 籤一次運輸合同(三次握手)
    • 下訂單(請求)
    • 生產貨物(伺服器計算結果)
    • 發起運輸(TCP 傳輸內容)
    • 收貨物(響應)
    • 結一次運輸合同的賬(四次揮手)
    • 籤一次運輸合同(三次握手)
    • 下訂單(請求)
    • 生產貨物(伺服器計算結果)
    • 發起運輸(TCP 傳輸內容)
    • 收貨物(響應)
    • 結一次運輸合同的賬(四次揮手)
  • http1.1 keep-alive
    【改進】運輸合同改成月結,複用 TCP 連結
    【問題】工廠無法同時生產多個訂單的貨物,需要上一個訂單收貨

    • 籤一次運輸合同(三次握手)
    • 下訂單(請求)
    • 生產貨物(伺服器計算結果)
    • 發起運輸(傳輸內容)
    • 收貨物(響應)
    • 下訂單(請求)
    • 生產貨物(伺服器計算結果)
    • 發起運輸(傳輸內容)
    • 收貨物(響應)
    • 結一次運輸合同的賬(四次揮手)
  • http1.1 pipeline
    【改進】可以同時發多個訂單了,通過收貨順序,來識別貨物對應的是那一次訂單的內容
    【改進】工廠可以同時生產多個訂單的貨
    【問題】訂單存在依賴關係,即使第二次訂單的貨物生產好了,也得等第一次訂單的貨物生產好並全部傳輸完,才能發貨。否則會被當做第一個訂單的貨

    • 籤一次運輸合同(三次握手)
    • 下訂單(第一個請求)
    • 下訂單(第二個請求)
    • 同時生產第一個批和第二批貨物(伺服器計算結果)
    • 按順序發第一個訂單的運輸(傳輸內容)
    • 按順序收貨物(響應,對應第一個響應)
    • 按順序發第二個訂單的運輸(傳輸內容)
    • 收貨物(響應,對應第二個響應)
    • 結一次運輸合同的賬(四次揮手)
  • http2
    【改進】將一個訂單的貨拆分成多個批次,為每個批次標識上是哪個訂單的貨
    【改進】由於能識別一批次貨品所屬訂單,最小粒度從一個訂單的貨,改為一批次的。原本按訂單運輸,現在改為按批次運輸,這個最小顆粒度的變化就是 http2 分幀:將一個響應或請求拆分成多個分幀片段
    【改進】最小粒度變成了批次,生產完一批次的貨品,就可以馬上傳輸,不需要等整個訂單的貨全部生產完才傳輸

    • 籤一次運輸合同(三次握手)
    • 下訂單(第一個請求)
    • 下訂單(第二個請求)
    • 同時生產第一個訂單和第二訂單的貨物(伺服器計算)
    • 每生產批次貨物,就給這批次的貨打上標籤,標識是哪個訂單的貨(分幀)
    • 準備好了一批次貨物,就發運輸,不需要管是哪個訂單的(傳輸)
    • 收貨,重新分揀是哪個訂單的貨(根據分幀標識對應是那一次請求的響應)
    • 每生產批次貨物,就給這批次的貨打上標籤,標識是哪個訂單的貨(分幀)
    • 準備好了一批次貨物,就發運輸,不需要管是哪個訂單的(傳輸)
    • 收貨,重新分揀是哪個訂單的貨(根據分幀標識對應是那一次請求的響應)
    • 直到所有貨物都傳輸完成
    • 結一次運輸合同的賬(四次揮手)
  • 總結

    • 可以看出,tcp 的分幀與 http2 的分幀是不同維度的區分
    • tcp 的分幀維度是一個趟次運輸(一個趟次運輸一個貨物),http2 的分幀維度是 一批貨物(可能是一個貨物,也可能是若干個貨物)
    • http2 分幀的本質是將原本一個訂單(一個請求或響應),拆分成多個批次(多個幀),縮小資料顆粒度,增加靈活性
  • 參考資料

為什麼要分幀

  • 本質上,只要給一個訂單的貨(響應)打上訂單(請求)標識,就可以標識是哪個訂單的,就可以解決先訂單依賴的問題(後一個訂單不需要等前一個訂單傳輸完),為什麼需要將訂單拆散為批次呢?

    • 車的數量(TCP 通道寬度,流量寬度)是有限的,拆散了並不是加快運輸過程
  • 拆成批次(分幀)是為了從根源支援資料的分配傳輸,如果一個訂單的量很大,按訂單發貨,就得等整個訂單的貨生產完成才能運輸。而拆成批次(分幀)就可以將粒度減低,生產一個批次就運輸一個批次,不需要等整個訂單的貨生產完成。

如何理解 http1.1 是文字協議,http2 是二進位制協議

  • stackoverflow 中對應的討論對應國內論壇
  • 文字協議,資訊傳輸過程經歷以下步驟

    • 編寫文字,由於規則比較鬆散,可能存在多餘的前後空格,多餘的換行等情況
    • 傳輸文字,傳輸的是 ASCII,即文字對應的編碼
    • 讀取文字,理解文字,識別 ASCII 碼組合起來的單詞,再通過字串匹配的方式匹配意義
  • 二進位制協議

    • 這裡的二進位制,主要體現在兩個方面「二進位制幀封裝」及「頭部壓縮」
    • 「二進位制幀封裝」即將資料打散,外包一層二進位制幀資料(用於標識當前幀的特性)

      • 所以是這一分幀層進行了二進位制封裝,而不是 http 的內容二進位制,所以更合適的稱呼應該是「增加了二進位制分幀層」
      • 這裡的二進位制幀資料,是用二進位制為顆粒度代表資料的含義,每個 0 和 1 代表特殊的含義
      • 而文字協議,是通過 ASCII 對應的單詞來表達含義,
      • 即代表資料的顆粒度不一樣了,原本是有若干個字母,現在是由若干個位元
    • 「頭部壓縮」

      • 通過靜態表和動態表的索引值來代表含義
      • 相當於雙方建立的臨時暗號

http2 頭部壓縮,如何做到瀏覽器動態表與伺服器動態表的同步

相關文章