談到HTTP版本,通常會有這樣的想法。
“反正網路上都是HTTP,不是嗎?1.1和2有什麼不同呢?”
“只要用新版本的HTTP/2不就行了嗎?”
總結來說:
-
HTTP/1.1和HTTP/2的差異不在於是“完全不同的協議”,而是如何更有效率地傳送相同的HTTP語意(方法/標頭/狀態碼等)。
-
在實際服務中,通常不是“要選擇其中一個”,而是伺服器同時支持兩者,客戶端選擇其中一個的結構。
接下來我會從開發者的角度整理出重點。
1. HTTP/1.1簡單總結
1) 文本基礎協議
HTTP/1.1是我們常見的這種請求/響應格式。
GET /index.html HTTP/1.1
Host: example.com
Connection: keep-alive
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
<html>...</html>
-
因為是可讀的文本,所以調試非常方便。
-
使用
curl、telnet、nc等工具也能輕易理解其結構。
2) 持久連接 + 管道化
HTTP/1.0的一個主要問題是每次請求都需要重新建立TCP連接,而
在HTTP/1.1中,基本上是持久連接(keep-alive),讓多個請求可以在同一連接上依次發送。
同時也有一項功能是HTTP管道化(pipelining):
-
不等待響應連續發送請求
-
按順序接收響應。
不過在實際瀏覽器中幾乎不使用,
因為仍然存在“必須按順序處理的結構”,所以性能問題依然存在。
3) HOL(Head-of-Line)阻塞問題
HTTP/1.1的一個典型瓶頸就是HOL(Head-of-Line)阻塞。
-
因為只能在一個連接中按順序處理請求,
-
如果最前面的請求變慢,後面的請求都必須一起等待。
-
因此,瀏覽器通常會在一個域名(origin)下打開多個TCP連接(例如最多6個)來減輕這個問題。
總結來說:
HTTP/1.1是“通過創建多個管道來減少瓶頸”的方式。
(多個TCP連接)
2. HTTP/2有什麼不同?
HTTP/2的目標非常明確。
-
減少延遲(latency)
-
更有效地使用網絡資源
提煉出關鍵詞:
-
二進制幀(Binary Framing)
-
基於流的多路復用(Multiplexing)
-
標頭壓縮(HPACK)
-
(原本) 伺服器推送(Server Push) – 事實上在瀏覽器中已經死亡
2-1. 文本 → 二進制幀
HTTP/1.1是逐行文本解析,而在HTTP/2中,所有的內容都被切割成幀(frame)這種二進制塊來傳送。
-
標頭使用HEADERS幀
-
主體使用DATA幀
-
這些幀屬於特定的流ID。
雖然開發者幾乎不會直接處理幀,
但這使得多路復用、標頭壓縮、優先級等功能得以實現。
2-2. 多路復用(Multiplexing)
這是最明顯的不同。
-
HTTP/1.1: 在一個TCP連接中依次處理請求-響應
-
HTTP/2: 在一個TCP連接中同時發送多個流
也就是說,
“不需要打開多個TCP連接,
而是在一個連接內將請求和響應合併同時發送。”
這樣的話:
-
當一個HTML頁面需要載入數十至數百個資源時,
-
可以保持一個連接同時載入資源,因此
-
在移動環境或高RTT環境下尤其獲益良多。
不過,在TCP層面仍然存有HOL阻塞,這一部分在HTTP/3(QUIC)中得到了更好的改進。
2-3. 標頭壓縮(HPACK)
HTTP請求/響應標頭中存在許多重複的內容。
-
Cookie、User-Agent、Accept-*等 -
每次請求可能需要消耗數百KB
HTTP/2使用HPACK的標頭壓縮技術
來減少這些標頭之間的重複。
-
經常使用的標頭會註冊到表中,並以短索引發送
-
僅有效編碼與前一請求不同的部分
這使得在請求頻繁的SPA / 資源豐富的頁面上獲益良多。
2-4. 伺服器推送(Server Push)事實上已經死亡
在HTTP/2初期,預先向客戶端推送CSS/JS等功能的伺服器推送(Server Push)曾被視為一大優勢,但在實際應用中:
-
實現難度較高,
-
快取/重複資源問題,
-
實際性能提升微乎其微,甚至惡化的案例
因此,Chrome/Chromium系列在2022年後默認禁用(Chrome for Developers)
Firefox也計劃在2024年左右刪除支持,在瀏覽器生態中幾乎已經結束該功能。
所以現在提到HTTP/2時,可以將伺服器推送視為“歷史功能”。
3. HTTPS、ALPN,以及“h2 vs http/1.1的選擇”
在實際服務中“用HTTP/1.1還是HTTP/2?”
客戶端和伺服器在TLS握手過程中會自動協商。
這項工作由ALPN(應用層協議協商)這個TLS擴展負責。
-
客戶端:“我既支持
h2也支持http/1.1” -
伺服器:“那我們用
h2吧”(或“我只支持http/1.1”)
Apache示例設定:
Protocols h2 http/1.1
這樣設置後:
-
支持HTTP/2的最新瀏覽器會自動使用HTTP/2(h2)
-
舊客戶端則會自動使用HTTP/1.1進行通信
大多數主要瀏覽器已經很好地支持HTTP/2,
相當多的網站也已經啟用HTTP/2。
4. “在什麼情況下分別使用?” – 開發視角總結
其核心問題將根據案例進行說明。
4-1. 一般網絡服務(面向瀏覽器)
接近正確的策略:
“默認開啟HTTPS + HTTP/2,
HTTP/1.1則作為回退就可以了。”
-
大多數網絡伺服器(Nginx、Apache、Envoy等)和CDN,只需打開HTTP/2支持選項便能自動協商。
-
在應用層幾乎沒有必要直接分開“這個請求用1.1,那個用2”。
也就是說,如果是新服務,應將‘啟用HTTP/2的HTTPS’視為默認值。
4-2. 內部API / 微服務通信
這裡有更多選擇。
-
如果已經從REST + HTTP/1.1運行良好,
則無需特別重寫為HTTP/2。 -
不過,
-
若在同一服務之間發送大量短請求
-
或者使用基於HTTP/2的gRPC協議,那麼
→ 使用HTTP/2會更自然。
-
也就是說,
-
“舊的遺留REST API” → 保持使用1.1 + 需要時在代理/負載均衡器處終止HTTP/2
-
“新導入gRPC,高頻微服務調用” → 積極利用HTTP/2
4-3. 調試、日誌、遺留環境
HTTP/1.1在某些情況下仍然有其價值。
-
由於是基於文本,在tcpdump、Wireshark中很容易查看內容
-
老舊的代理/防火牆/客戶端可能不支持HTTP/2
-
在一些簡單內部工具、測試伺服器中,使用HTTP/2並不必要
實際上在很多環境中:
-
外部(瀏覽器)↔ 前端代理(CDN/負載均衡器) : HTTP/2
-
代理 ↔ 後端服務 : HTTP/1.1
往往出現結構混合的情況。
5. 對於“是否只能使用HTTP/2?”的現實回答
理論上:
“如果是新建的公開網絡服務,可以考慮以HTTP/2作為默認。”
是有道理的。
但在實務中:
-
完全消除HTTP/1.1是困難的
-
老舊客戶端或特殊環境仍然只能使用1.1
-
在調試/工具/內部系統等情況下,1.1更為方便
-
-
從伺服器的角度來看“支持兩者”是較為普遍的
-
在網絡伺服器的設置中如
h2 http/1.1一起開放 -
讓客戶端自動選擇支持的最佳協議
-
-
考慮到HTTP/3(QUIC)的時代
-
最新的瀏覽器/服務已經支持HTTP/3
-
但這通常也是“同時開放HTTP/1.1 + HTTP/2 + HTTP/3”,讓客戶端進行協商。
-
因此,現實的結論是:
“與其僵持使用HTTP/2,
不如將HTTP/2作為默認啟用,而將HTTP/1.1作為自然回退”更為理想。”
。

6. 總結整理
總結一下:
-
HTTP/1.1
-
基於文本
-
持久連接 + (理論上的)管道化
-
由於HOL阻塞問題,瀏覽器使用多個TCP連接
-
-
HTTP/2
-
二進制幀
-
在一個TCP連接中同時處理多個流的多路復用
-
HPACK標頭壓縮
-
伺服器推送在實務中幾乎可以說是死亡狀態
-
-
使用策略
-
外部網絡(面向瀏覽器):啟用HTTPS + HTTP/2,HTTP/1.1作為回退
-
內部API:原有REST可保持使用1.1,如高頻/流式/gRPC則積極利用HTTP/2
-
調試/遺留:HTTP/1.1仍然便利且有用
-
開發者應該記住的一條:
“在應用代碼中不要為版本選擇煩惱,
將HTTP/2設置在伺服器中,讓其他問題交給協議協商(ALPN)處理。”
目前沒有評論。