HTTP/2_Server_Push

**HTTP/2**（超文字傳輸協定第 2 版，最初命名為 **HTTP 2.0**），簡稱為 **h2**（基於 TLS/1.2 或以上版本的加密連接）或 **h2c**（非加密連接），是 HTTP 協定的的第二個主要版本，使用於全球資訊網。

HTTP/2 是 HTTP 協定自 1999 年 HTTP 1.1 的改進版 RFC 2616 發布後的首個更新，主要基於 SPDY 協定。它由網際網路工程任務組（IETF）的 Hypertext Transfer Protocol Bis（httpbis）工作小組進行開發。該組織於 2014 年 12 月將 HTTP/2 標準提議遞交至 IESG 進行討論，於 2015 年 2 月 17 日被批准。

HTTP/2 標準於 2015 年 5 月以 RFC 7540 正式發表。HTTP/2 的標準化工作由 Chrome、Opera、Firefox、Internet Explorer 11、Safari、Amazon Silk 及 Edge 等瀏覽器提供支援。

多數主流瀏覽器已經在 2015 年底支援了該協定。此外，根據 W3Techs 的資料，截至 2021 年 10 月，全球有 46.5% 的網站支援了 HTTP/2。

## 協定的制定

協定制定伊始，工作群組章程關注了下列目標和受關心的問題：

* 建立一個協商協定標準，即**應用層協定協商（ALPN）** ，以便客戶端能夠從 HTTP/1.0、HTTP/1.1、HTTP/2 乃至其他非 HTTP 協定中做出選擇。
* 與 HTTP/1.1 在請求方法、狀態碼乃至 URI 和絕大多數 HTTP 頭部欄位等方面保持高度相容性。
* 通過以下舉措，減少網路延遲，提高瀏覽器的頁面載入速度：
  * 對 HTTP 頭欄位進行資料壓縮（即 HPACK 演算法）；
  * HTTP/2 伺服器端推播（Server Push）；
  * 請求管線；
  * 修復 HTTP/1.0 版本以來未修復的隊頭阻塞問題；
  * 對資料傳輸採用多路復用，讓多個請求合併在同一 TCP 連接內。
* 支援現有的 HTTP 應用場景，包括桌面和行動裝置瀏覽器、網路 API、不同規格的網路伺服器和正向代理、反向代理伺服器軟體、防火牆和 CDN 等。

Facebook 對各方案進行了評價並最終推薦了 SPDY 協定。HTTP 2.0 的首個草稿於 2012 年 11 月發布，其內容基本和 SPDY 協定相同。

## 協定之間的的比較

### HTTP/2 與 HTTP/1.1 比較

HTTP/2 相比 HTTP/1.1 的修改並不會破壞現有程式的工作，但是新的程式可以藉由新特性得到更好的速度。

HTTP/2 保留了 HTTP/1.1 的大部分語意，例如請求方法、狀態碼乃至 URI 和絕大多數 HTTP 頭欄位一致。而 HTTP/2 採用了新的方法來編碼、傳輸客戶端和伺服器之間的資料。

### HTTP/1.1 與 SPDY 的區別

SPDY（發音同「speedy」）是一個由 Google 主導的 HTTP 替代協定。SPDY 一開始主要關注降低延遲，採用了 TCP 通道，但是使用了不同的協定來達到此目的。其與 HTTP/1.1 相比，主要的改變有：

* 實現無需先入先出的多路復用
* 為簡化客戶端和伺服器開發的訊息 — 影格機制
* 強制性壓縮（包括 HTTP 頭部）
* 優先級排序
* 雙向通訊

### HTTP/2 與 SPDY 的比較

HTTP/2 的開發基於 SPDY 進行躍進式改進。在諸多修改中，最顯著的改進在於，HTTP/2 使用了一份經過客製化的壓縮演算法，基於霍夫曼編碼，以此替代了 SPDY 的動態流壓縮演算法，以避免對協定的 Oracle 攻擊 —— 這一類攻擊以 CRIME 為代表。此外，HTTP/2 禁用了諸多加密套件，以保證基於 TLS 的連接的前向安全。

## 新特性

在 HTTP/2 的第一版草案（對 SPDY 協定的復刻）中，新增的效能改進不僅包括 HTTP/1.1 中已有的多路復用，修復隊頭阻塞問題，允許設定設定請求優先級，還包含了一個頭部壓縮演算法（HPACK）。此外， HTTP/2 採用了二進位而非明文來打包、傳輸客戶端和伺服器之間的資料。

### 影格、訊息、流和 TCP 連接

有別於 HTTP/1.1 在連接中的明文請求，HTTP/2 與 SPDY 一樣，將一個 TCP 連接分為若干個流（Stream），每個流中可以傳輸若干訊息（Message），每個訊息由若干最小的二進位影格（Frame）組成。這也是 HTTP/1.1 與 HTTP/2 最大的區別所在。HTTP/2 中，每個使用者的操作行為被分配了一個**流編號（S**tream ID），這意味著使用者與伺服器端之間建立了一個 TCP 通道；協定將每個請求分割為二進位的控制影格與資料框部分，以便解析。這個舉措在 SPDY 中的實踐表明，相比 HTTP/1.1，新頁面載入可以加快 11.81% 到 47.7%

### HPACK 演算法

HPACK 演算法是新引入 HTTP/2 的一個演算法，用於對 HTTP 頭部做壓縮。其原理在於：

* 客戶端與伺服器端根據 RFC 7541 的附錄 A，維護一份共同的靜態字典（Static Table），其中包含了常見頭部名及常見頭部名稱與值的組合的代碼；
* 客戶端和伺服器端根據先入先出的原則，維護一份可動態添加內容的共同動態字典（Dynamic Table）；
* 客戶端和伺服器端根據 RFC 7541 的附錄 B，支援基於該靜態哈夫曼碼錶的哈夫曼編碼（Huffman Coding）。

### 伺服器推播

網站為了使請求數減少，通常採用對頁面上的圖片、指令碼進行極簡化處理。但是，這一舉措十分不方便，也不高效，依然需要諸多 HTTP 連結來載入頁面和頁面資源。

HTTP/2 引入了**伺服器推播**，即伺服器端向客戶端傳送比客戶端請求更多的資料。這允許伺服器直接提供瀏覽器彩現頁面所需資源，而無須瀏覽器在收到、解析頁面後再提起一輪請求，節約了載入時間。

## 瀏覽器支援

截至 2015 年末，主要的瀏覽器的最新版本已經支援 HTTP/2 這一協定。其中：

* Google Chrome、Mozilla Firefox、Microsoft Edge 和 Opera 已支援 HTTP/2，並預設啟用。
* Internet Explorer 自 IE 11 開始支援 HTTP/2，並預設啟用。

### h2c 的支援度

HTTP/2 的設計本身允許非加密的 HTTP 協定，也允許使用 TLS 1.2 或更新版本協定進行加密。協定本身未要求必須使用加密， 惟多數客戶端（例如 Firefox、Chrome、Safari、Opera、IE 和 Edge 等）的開發者聲明，他們只會實現通過 TLS 加密的 HTTP/2 協定，這使得經 TLS 加密的 HTTP/2 成為了事實上的強制標準，而 h2c 事實上被主流瀏覽器廢棄。

### SPDY 登出歷史舞台

2015 年 9 月，Google 宣布了移除對 SPDY 支援的計劃，擁抱 HTTP/2，並將在 Chrome 51 中生效。

## HTTP/2 的實現

HTTP/2 工作群組在其官方 Github 上羅列了諸多已經支援該協定的代碼實現。

## 批評與爭議

HTTP/2 的開發過程乃至協定本身都曾受到批評。

### 針對協定開發本身

FreeBSD 和 Varnish cache 的開發者保羅 - 恆寧・坎瀑批評稱，這個標準檔案的準備過程短得不切實際，而且未基於除了 SPDY 之外的任何協定，以至於其他協定失去了對草案進行改進的機會。Kampala 批評說，這個協定本身與 HTTP 不一致，而且還毫無必要地變得極為複雜。他還認為，這個協定違背了網際網路協定的分層原則，例如說，將本屬於 TCP 傳輸層的流控制（flow control）功能放入了協定中。

### 針對加密的爭議

一開始，以 HTTP 工作群組某位主席為首的成員在郵寄清單建議引入強制使用 TLS 協定實現的 HTTP/2（Mandatory TLS in HTTP/2.0），這招致了爭議。批評者認為，加密增加了十分不必要的開銷，而且很多 HTTP 服務實際上無需加密，提供者也無意為此花費更多的資源。而支持者認為，實踐中 TLS 加密的開銷微不足道。

Poul-Henning Kamp 批評 IETF 在制定 HTTP/2 時，遵循了一個特定的「政治議程」（political agenda），壓縮了討論的空間。

強制加密議程的批評者認為，其基於現有的憑證框架，對於開源社群並非新創造，亦不是獨特的。2013 年，一位思科員工表示，現有憑證模型與路由器一類的小型化裝置並不相容，因為現有的憑證框架需要為每張憑證付出不可避免的成本，還需要進行每年更新的流程。工作群組最終未能在強制加密這一點上達成一致，但是大部分客戶端只實現了基於 TLS 的 HTTP/2，使之成為事實標準。

HTTP/2 也被批評未能支援機會性加密，即類似 SMTP 中存在已久的 STARTTLS 一樣能抵禦被動監視的措施。 批評者指出，HTTP/2 的提議違背了 IETF 自身制定的《最佳實踐 188》（BCP 188） 即 RFC 7258。這份檔案指出，被動監視應被當作一種攻擊，IETF 指定的標準應當設定抵禦這種攻擊的措施（例如機會性加密）。目前，已經有一系列機會性加密規範被提出，工作群組也制定了 draft-ietf-httpbis-http2-encryption-01 這一官方版方案。

## 參考資料

## 參見

* 超文字傳輸協定（HTTP）
* SPDY (已計劃隨 NPN 一起淘汰)
* 多路復用
* QUIC
* WebSocket

## 外部連結

* http://tools.ietf.org/wg/httpbis/ （頁面存檔備份，存於網際網路檔案館） 工作群組首頁
* https://http2.github.io/ （頁面存檔備份，存於網際網路檔案館） HTTP/2 協定官網
* RFC 7540 – 超文字傳輸協定版本 2 (HTTP/2)
* RFC 7541 – HPACK: 為 HTTP/2 制定的頭部壓縮演算法
* SPDY Protocol (draft-mbelshe-httpbis-spdy-00)
* HTTP Speed+Mobility (draft-montenegro-httpbis-speed-mobility-01)
* Proposal for a Network-Friendly HTTP Upgrade (draft-tarreau-httpbis-network-friendly-00)