前言
HTTP/2協(xié)議在TCP連接之初進(jìn)行協(xié)商通信,只有協(xié)商成功,才會涉及到后續(xù)的請求-響應(yīng)等具體的業(yè)務(wù)型數(shù)據(jù)交換。
HTTP版本標(biāo)識符
- h2,基于TLS之上構(gòu)建的HTTP/2,作為ALPN的標(biāo)識符,兩個字節(jié)表示,0x68, 0x32,即https
- h2c,直接在TCP之上構(gòu)建的HTTP/2,缺乏安全保證,即http
- 在HTTP/2 RFC文檔出現(xiàn)之前,以上版本字段需要添加上草案版本號,類似于h2-11,h2c-17
HTTP/2 請求過程
針對直接建立在標(biāo)準(zhǔn)TCP之上HTTP2,在未知服務(wù)器是否提供HTTP/2支持之前,可以依賴現(xiàn)有HTTP/1.1進(jìn)行試探。
HTTP版本的請求內(nèi)容
- 客戶端發(fā)起請求,只有請求報頭:
GET / HTTP/1. 1
Host: server. example. com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>
- 服務(wù)器若不支持HTTP/2,直接按照HTTP/1.1響應(yīng)即可
HTTP/1. 1 200 OK
Content-Length: 243
Content-Type: text/html
. . .
服務(wù)器支持HTTP/2,通知客戶端一起切換到HTTP/2協(xié)議下吧
HTTP/1. 1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c
[ HTTP/2 connection . . .
- 101響應(yīng)空行之后,服務(wù)器必須發(fā)送的第一個幀為SETTINGS幀(其負(fù)載可能為空)作為連接序言
- 客戶端接收到101響應(yīng)后,也必須發(fā)送一個序言作為響應(yīng),其邏輯結(jié)構(gòu):
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n // 純字符串表示,翻譯成字節(jié)數(shù)為24個字節(jié)
SETTINGS幀 // 其負(fù)載可能為空
服務(wù)器端和客戶端所發(fā)送的連接序言有所不同。
- 客戶端可以馬上發(fā)送請求幀或其它幀過去,不用等待來自服務(wù)器端的SETTINGS幀
- 任一端接收到SETTINGS幀之后,都需要返回一個包含確認(rèn)標(biāo)志位SETTIGN作為確認(rèn)
- 其它幀的正常傳輸
HTTP/2的直接連接
客戶端預(yù)先知道服務(wù)器提供HTTP/2支持,可以免去101協(xié)議切換的流程開銷。
具體流程:
- 客戶端必須首先發(fā)送一個連接序言,其邏輯結(jié)構(gòu):
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n // 純字符串表示,翻譯成字節(jié)數(shù)為24個字節(jié)
SETTINGS幀 // 其負(fù)載可能為空
- 發(fā)送完畢序言之后,客戶端可以不用等待來自服務(wù)器端響應(yīng),馬上發(fā)送HTTP/2其它幀
- 服務(wù)器端接收到客戶端的連接序言之后,需要發(fā)送一個SETTINGS幀作為連接序言
- 任一端接收到SETTINGS幀之后,都需要返回一個包含確認(rèn)標(biāo)志位SETTIGN作為確認(rèn)
- 其它幀的正常傳輸
HTTPS版本建立連接
HTTP/2安全版本在TLS上構(gòu)建,協(xié)商采用的ALPN擴(kuò)展協(xié)議,采用“h2”作為協(xié)議標(biāo)識符(http版本則是“h2c”)。一定程度上可認(rèn)為不存在試探是否支持或直接連接的煩惱,因為這個過程直接在TLS層協(xié)商而成。
流程如下:
- 客戶端和服務(wù)器端TLS層協(xié)商
- 客戶端發(fā)送連接序言(同上表示,PRI + SETTINGS)
- 接收到客戶端連接序言之后,服務(wù)器端發(fā)送連接序言
- 雙方各自確認(rèn)SETTINGS幀
- 其它幀的正常傳輸
HTTPS和HTTP Upgrade方式協(xié)商
HTTPS協(xié)商是強(qiáng)制,封裝在TLS之上ALPN擴(kuò)展實現(xiàn),HTTP只有非直接連接方式才會存在通過101 協(xié)議切換方式進(jìn)行升級。
這里有一張圖形象說明其流程。

統(tǒng)一的連接過程
這里不論是HTTP還是HTTPS,在兩端成功協(xié)商之后(或HTTP的直接連接),其連接過程都是一樣的

注意事項
- 客戶端發(fā)起的HTTP/1.1請求,其流標(biāo)識符為1,默認(rèn)優(yōu)先級;半關(guān)閉“half closed”狀態(tài),一旦完成HTTP/2的連接,將被應(yīng)用于響應(yīng)
- 文檔提到的客戶端可以通過HTTP Alternative Services(簡稱為[ALT-SVC],類似于CNAME機(jī)制)獲得通知服務(wù)器是否支持HTTP/2,但目前看來僅僅是草案建議而已
- 連接序言用于最后兩端協(xié)商確認(rèn)雙方要使用HTTP/2協(xié)議,建立初始化的HTTP/2連接環(huán)境
- 客戶端若知服務(wù)器支持HTTP/2,可免去通過HTTP/1.1 101協(xié)議切換方式進(jìn)行升級,在建立連接后即可發(fā)送序言,否則只能在接收到服務(wù)器端101響應(yīng)后發(fā)送序言
- 建立在TLS上的HTTP/2通過ALPN擴(kuò)展協(xié)商機(jī)制取代101協(xié)議切換
- 連接序言所包含的SETTINGS幀其負(fù)載可以為空
- 針對一個TCP連接,服務(wù)器第一個要發(fā)送的幀必須是SETTINGS幀
- 為了避免不必要延遲,客戶端可以在發(fā)送完畢序言之后發(fā)送幀數(shù)據(jù),不用等待來自服務(wù)器端的序言SETTINGS幀
- 客戶端接收到服務(wù)器端作為序言的SETTINGS幀,需要遵守其設(shè)定
- 在一些環(huán)境下需要提供一個順序機(jī)制,允許服務(wù)器在客戶端發(fā)送業(yè)務(wù)幀之前發(fā)送SETTINGS,這需要客戶端配合
- 客戶端和服務(wù)器端任何一方接收到無效連接序言需要拋出PROTOCOL_ERROR類型連接錯誤,若收到GOAWAY幀,可忽略
小結(jié)
HTTP/2連接的建立協(xié)商機(jī)制比HTTP/1.1稍微復(fù)雜了一些。
對比明文版的HTTP/1.1和HTTP/2完成一次請求-響應(yīng):
- HTTP/1.1在建立建立之后,只需要發(fā)送請求報文數(shù)據(jù)
- HTTP/2客戶端需要在連接建立之初馬上發(fā)送一個連接序言過去,然后才是正常請求
- 兩端(客戶端+服務(wù)器端)的兩次完整的連接序言+確認(rèn)的交互流程,多了兩次往返過程
在弱網(wǎng)絡(luò)環(huán)境下,會不會加重網(wǎng)絡(luò)負(fù)載,只能拭目一看了。
引用
- 《Implementing HTTP/2 client in 60 minutes》