伯陽的網路筆記(三):HTTP/2
因為疫情期間在外當志願者,晚上回家無聊翻翻網路知識,權當記錄了。
初始動筆:2019-02-06
修改時間:2019-03-27
GitHub Repo:BoyangBlog
1. HTTP/1.x 的問題
不得不說, HTTP/1.1 是一個偉大的協議,現在仍然有非常多的網站使用它,充分說明瞭它的健壯、巧妙。但是,它畢竟是一個建立於網際網路時代前的協議,雖然已經很有預見性了,但是仍然有些過時了。主要有以下幾個問題:
- HTTP 只允許每個 TCP 連線有一個未完成的請求,會有隊首阻塞的問題;
- 對於同一個域名,瀏覽器最多可以同時建立 6~8 個 TCP 連線;
- Header 有點過大了;
- 為了儘可能減少請求數,需要做合併檔案、減少影象等優化工作,但是這無疑造成了單個請求內容變大延遲變高的問題;
- 明文傳輸。
所以,隨著求變的聲音越來越多,HTTP/2 應聲而出。
2. SPDY
等一下,正式講到 HTTP/2 之前,我們需要先提一下 SPDY。
因為遲遲沒有 HTTP/1.1 的優化出線,谷歌自己推出了一個新的網路協議,叫做 SPDY,它的很多設計,被採用到了 HTTP/2 當中,比如說多路複用、二進位制分幀、頭部壓縮、伺服器推送等等。
3. HTTP/2 簡介
在2012年,W3C向社會徵求 HTTP/2 的建議,然後決定將 SPDY 當做制定標準的基礎。目標上, HTTP/2 致力於突破上一代協議眾所周知的效能限制,對 HTTP/1.x 進行擴充套件,而非替代,核心概念不會改變。下圖展示了 HTTP/1 和 HTTP/2 的區別。
它做了很多改變,下面細講。 不過在講之前,要先解釋 HTTP/2 中的幾個概念:
- 流
已建立的連線上的雙向位元組流 - 訊息
與邏輯訊息對應的完整的一系列資料幀 - 幀
HTTP/2 通訊的最小單位
所有的 HTTP/2 通訊都是在一個 TCP 連線上完成,這個連線可以承載任意數量的雙向資料流。相應的,每個資料流以訊息的形式傳送,而訊息由一個或多個幀組成,這些幀可以亂序傳送,然後再根據每個幀首部的流表示符重新組裝。
二進位制分幀
HTTP/2 效能增強的核心,全在於新增的二進位制分幀層,它定義瞭如何封裝 HTTP 訊息並在客戶端與伺服器之間傳輸。
這裡的”層”,指的是位於會話層和應用層之間的一個新的機制:HTTP 的語義不受影響,不同的是傳輸期間對它們的編碼方式改變了。HTTP/1.x 以換行符作為純文字的分隔符,而 HTTP/2 將所有傳輸的資訊分割為更小的訊息和幀,並對他們採用了二進位制格式的編碼。
多向請求和響應
在 HTTP/1.x 中,如果客戶端想要傳送多個並行的請求以改進效能,那麼必須使用多個 TCP 連線;每個連線每次只交付一個響應,多個響應必須要排隊。更糟糕的在於,這樣非常容易發生隊首堵塞,從而造成 TCP 連線效率低下。
HTTP/2 中的二進位制分幀,突破了這種限制,客戶端和伺服器可以把 HTTP 訊息分解為互不依賴的幀,然後亂序傳送,然後在另一端把他們重新組合起來。如下如所示。
將 HTTP 訊息分解為獨立的幀,交錯傳送,然後在另外一端重新組裝是 HTTP/2 最重要的一項增強。它帶來了以下幾個優點:
- 可以並行交錯的傳送請求,請求之間互不影響;
- 可以並行交錯的傳送響應,響應之間互不幹擾;
- 只使用一個連線即可並行傳送多個請求和響應(多路複用);
- 消除不必要的延遲;
- 不必再繼續在為了繞過 HTTP/1.x 的限制做很多工作;
- ......
總之,這個技術解決了 HTTP/1.1 中存在的隊首阻塞問題,也消除了並行處理和傳送請求及響應時對多個連線的依賴。
流量控制
在同一個 TCP 上傳輸多個資料流,就意味著要共享頻寬。標定資料流的優先順序有助於按序交付,但只有優先順序還不足以確定多個資料流或多個連線之間的資源分配。所以,HTTP/2 提供了一個簡單的機制:
- 流量控制基於每一跳進行,而非端到端的控制;
- 流量控制基於視窗更新幀進行,即接收方廣播自己準備接受某個資料流的多少位元組,以及對整個連線要接收多少位元組;
- 流量控制視窗大小通過 WINDOW_UPDATE 幀更新;
我們可以發現,它和 TCP 流量控制非常類似,事實上這兩個機制是一樣的。
這個由程式設計師手動控制。
伺服器推送
伺服器可以對一個客戶端請求傳送多個響應。換句話說,除了對最初請求的響應外,伺服器還可以額外向客戶端推送資源,而無需客戶端明確地請求。
因為有些資源,比如去線上閱讀說一本書,就可以預測到下一步可能的閱讀的頁面,進而提前進行快取。
首部壓縮
HTTP 的每一次通訊都會帶一組完整的首部,用於描述傳輸的資源及其屬性。在 HTTP/1.1 中,這些資料都是以純文字的形式傳送的,通常會給每個請求增加 500~800 位元組的負荷;如果再算上 cookie ,增加的負荷可能會加大到上千位元組。為了減少這些開銷,HTTP/2 會壓縮首部資料。
HTTP/2 連線的兩端都知道已經發送了哪些首部,這些首部是什麼,從而可以針對之前的資料只編碼傳送差異資料。
4. 加密
雖然一直有加入 TLS 的提議,但是最後 HTTP/2 並未強制加入 TLS。只是有些網站會加上。
5. HTTP/2 和 HTTP/3
HTTP/2 依然是以 TCP 作為基礎的,但是 TCP 依然會有三次握手消耗時間,為了優化它,谷歌專門搞了一個基於 UDP 協議的 QUIC 協議。這個協議正在被一些大廠使用,但是因為源於 UDP 協議,有可能被運營商破壞,前景依然需要觀察。
QUIC的相關原理可以檢視科普:QUIC協議原理分析這篇文章。
總結
總的來說,HTTP/2 是基於 HTTP/1.1 進行的拓展,有效的優化了速度和資料量。在多路複用、二進位制分幀、頭部壓縮、伺服器推送上的優化非常的精妙和讓人陶醉。
引用
RFC7540:Hypertext Transfer Protocol Version 2 (HTTP/2)
《Web效能權威指南》