gRPC 之流式呼叫原理 http2 協議分析(四)

a_wei發表於2019-09-01

HTTP/1協議回顧

  • HTTP(Hypertext transfer protocol)超文字傳輸協議
  • HTTP協議在7層傳輸架構中屬於應用層協議,其依賴TCP協議
  • HTTP協議由請求和響應兩部分組成,是一個標準的客戶端伺服器模型
  • HTTP預設埠號80,https預設埠號443
  • HTTP協議透過URL(統一資源定位符-Uniform-Resource-Locator)來定位網際網路上的資源地址
  • HTTP是一個無狀態的面向連線的協議,無狀態不代表HTTP不能保持長連線,無狀態指的是HTTP不具備事務記憶能力,也就是下一次的請求不會記住上一次的請求資訊。
  • HTTP協議0.9和1.0版本使用非持續性連線,也就是一次請求一次響應,連線就會關閉,而從HTTP協議1.1開始,預設開啟了Keep-Alive,保持長連線,就是說一次請求結束後,連線不會馬上關閉,下一次請求會繼續使用這個連線,但長連線不代表一直不關閉,一段時間後這個連線就會關閉。

HTTP的請求和響應分別都有請求行/響應行,首部,實體組成的,如下圖

【GoLang 那點事】gRPC之流式呼叫原理http2協議分析

HTTP2協議分析

什麼是HTTP2
  • HTTP / 2並不是對HTTP協議的重寫,相對於HTTP / 1,HTTP / 2的側重點主要在效能。請求方法,狀態碼和語義和HTTP / 1都是相同的,可以使用與HTTP / 1.x相同的API(可能有一些小的新增)來表示協議。
  • HTTP / 2主要有兩個規範組成
    1. Hypertext Transfer Protocol version 2 (超文字傳輸協議版本2)
    2. HPACK - HTTP / 2的頭壓縮 (HPACK是一種頭部壓縮演算法)
  • 這兩個規範的連線如下
  • https://httpwg.org/specs/rfc7540.html (第一個)
  • https://httpwg.github.io/specs/rfc7541.htm... (第二個)
HTTP2中的一些概念
  • 幀:資料通訊的最小資訊單位
  • 流:存在與TCP連線中的一個虛擬通道(雙向的,能往過流,也能往回流)
HTTP2的特性
  • HTTP / 2支援HTTP / 1.1的所有核心功能,但旨在透過多種方式提高效率
  • HTTP/2採用二進位制傳輸資料,而非HTTP/1的文字格式傳輸
  • HTTP / 2基本協議單元是幀,比如head(頭部資訊)幀,data(傳輸資料細資訊)幀
  • HTTP / 2使用流技術支援多路複用,也就是說提供了在單個連線上覆用HTTP請求和響應的能力, 多個請求或響應可以同時在一個連線上使用流.
  • HTTP / 2支援壓縮頭部幀,允許將多個請求壓縮成成一個分組,而且在客戶端和伺服器端分別頭部資訊建立索引,相同的表頭只需要傳輸索引就可以。
  • HTTP / 2支援對請求劃分優先順序(就是流的優先順序)
  • HTTP / 2支援Server Push技術
  • 下面一張圖來對比HTTP/1和HTTP/2的請求過程:

【GoLang 那點事】gRPC之流式呼叫原理http2協議分析

  • 由圖得知,傳送3個請求,在HTTP/1中是按照順序,一起請求,一次響應,而HTTP/2協議可以做到在一個TCP連線中並行執行,而不用按照順序一對一。
HTTP2的原理
多路複用
  • HTTP/2 將每一個請求變成流,每一個流都有自己的ID,有自己的優先順序,這些流可以由客戶端傳送到服務端,也可以由服務端傳送到客戶端,將資料劃分為幀,頭部資訊為head幀,實體資訊為data幀,最後將這些流亂序傳送到一個TCP連線中,如下圖:

【GoLang 那點事】gRPC之流式呼叫原理http2協議分析

  • HTTP/2中,在一個瀏覽器同域名下的所有請求都是在單個連線中完成,這個連線可以承載任意數量的雙向資料流,每個資料流都以訊息的形式傳送,而訊息又由一個或多個幀組成,多個幀之間可以亂序傳送,根據幀首部的流標識可以將多個幀重新組裝成一個流。

  • 在HTTP/1中,如果想併發傳送多個請求,必須建立多個TCP連線,而且瀏覽器為了減少負載,會對同一域名下的TCP連線做限制,這樣當請求量比較大時,會引起阻塞,如下圖,Stalled 阻塞已經達到159ms了,

【GoLang 那點事】gRPC之流式呼叫原理http2協議分析

伺服器推送
  • HTTP /1中客戶端往服務端傳送請求嚴格遵守一個請求,一個響應,比如客戶端請求展示網頁時,服務端發揮HTML內容,瀏覽器解析時傳送css,js請求,服務端又返回css,js檔案,那麼服務端為什麼不能在返回網頁時就推送css,js內容給客戶端呢,在HTTP /2中這已功能已經支援,

  • 服務端主動推送也會遵守同源策略,不會隨便推送第三方的資源到客戶端

  • 如果服務端推送資源是唄客戶端快取過的,客戶端是有權力拒絕服務端的推送的,瀏覽器可以透過傳送RST_STREAM幀來拒收。

  • 每一個服務端推送的資源都是一個流

    頭部壓縮
  • HTTP /1的請求頭較大,而且是以純文字傳送,HTTP/2對訊息頭進行了壓縮,採用的是HACK演算法,能夠節省訊息頭佔用的網路流量,其主要是在兩端建立了索引表,訊息頭在傳輸時可以採用索引,而HTTP/1.x每次請求,都會攜帶大量冗餘頭資訊,浪費了很多頻寬資源。

  • HACK演算法可以參考: https://www.zcfy.cc/article/1969

幀的描述
  • 所有幀都以固定的9位元組頭開頭,後跟可變長度的有效載荷,組成如下:
  • 長度:幀有效負載的長度表示為無符號的24位整數
  • 型別:8位型別的幀,幀型別確定幀的格式和語義
  • 標誌:為特定於幀型別的布林標誌保留的8位欄位
  • R:保留的1位欄位。該位的語義未定義
  • 流識別符號:流識別符號,表示為無符號31位整數,客戶端發起流識別符號必須時奇數,服務端發起的流識別符號必須是偶數

9位元組總共是:9 * 8 = 72位
上面的描述 24 + 8 + 8 +1 + 31 = 72位

gRPC和HTTP2的關係

  • gRPC設計時的初衷:gRPC的設計目標是在任何環境下執行,支援可插拔的負載均衡,跟蹤,執行狀況檢查和身份驗證。它不僅支援資料中心內部和跨資料中心的服務呼叫,它也適用於分散式計算的最後一公里,將裝置,移動應用程式和瀏覽器連線到後端服務,同時,它也是高效能的,而HTTP /2恰好支援這些。
  • HTTP /2天然的通用性滿足各種裝置,場景
  • HTTP /2的效能相對來說也是很好的,除非你需要極致的效能
  • HTTP /2的安全性非常好,天然支援SSL
  • HTTP /2的鑑權也非常成熟
  • gRPC基於HTTP /2多語言實現也更容易

參考文章

歡迎大家關注微信公眾號:“golang那點事”,更多精彩期待你的到來

【GoLang 那點事】gRPC之流式呼叫原理http2協議分析

本作品採用《CC 協議》,轉載必須註明作者和本文連結
那小子阿偉

相關文章