http2 協(xié)議簡(jiǎn)介
h2 專注于性能押框,最大的目標(biāo)在于用戶和網(wǎng)站之間只用一條連接岔绸。其h2 的推出并沒有改變http1.1 的基本語義。h2的目的是響應(yīng)復(fù)用橡伞,頭部壓縮來提高極致的性能盒揉。
其特性在 之前的文章中也做過介紹 http://www.reibang.com/p/3ea9b33c4678
核心概念
-
連接 Connection
:1個(gè)TCP連接包含多個(gè)Stream。 -
數(shù)據(jù)流 Stream
:一個(gè)雙向通訊數(shù)據(jù)流兑徘,包含1條或多條 message刚盈。 -
消息 Message
:對(duì)應(yīng)HTTP/1 中的請(qǐng)求或者響應(yīng),包含一個(gè)或者多條 Frame -
數(shù)據(jù)幀
: 最小單位挂脑,以二進(jìn)制壓縮格式存放 HTTP/1 中的內(nèi)容藕漱。
一個(gè)消息是由 Headers 幀和DATA 幀組成的。
流最域,消息谴分,幀 之間的關(guān)系
抓包可以看到 1號(hào) Stream 流 傳遞了 一個(gè) GET 請(qǐng)求牺蹄。1號(hào) Stream 流也進(jìn)行了回復(fù)(HEADER+DATA)
在一條 Connection 中,不同的流可以穿插傳遞薄翅,但是同一條流的達(dá)到順序必須是有序的沙兰,比如1號(hào)流氓奈,流內(nèi)的 幀必須有序。
這就是傳輸中無序鼎天,接收時(shí)組裝舀奶。
幀格式
每個(gè)幀標(biāo)準(zhǔn)為9個(gè)字節(jié) (可理解為幀頭)
幀中指明了其所屬于哪一個(gè) Stream流 (Stream Identifier)其占了31 位。
由此可見斋射,一個(gè)幀中最重要的就是 Stream Id 了育勺。其余的內(nèi)容為
-
Length
: 代表整個(gè) frame 的長(zhǎng)度,用一個(gè) 24 位無符號(hào)整數(shù)表示 -
Type
: 定義 frame 的類型罗岖。幀類型決定了幀主體的格式和語義涧至,如果 type 為 unknown 應(yīng)該忽略或拋棄。 -
Flags
:是為幀類型相關(guān)而預(yù)留的布爾標(biāo)識(shí)南蓬。標(biāo)識(shí)對(duì)于不同的幀類型賦予了不同的語義赘方。 -
R
: 是一個(gè)保留的比特位。這個(gè)比特的語義沒有定義弱左,發(fā)送時(shí)它必須被設(shè)置為 (0x0), 接收時(shí)需要忽略。 -
Frame Payload
: 是主體內(nèi)容科贬,由幀類型決定
下圖為wireshark中抓取的幀泳梆,上述的幀格式可以對(duì)比找到
正是將每一個(gè)幀關(guān)聯(lián)到流上。才實(shí)現(xiàn)了多路復(fù)用胞皱。這個(gè)多路復(fù)用指的是很多個(gè)流之間的幀隨意穿插反砌。比如客戶端收到 1流的 1 幀宴树,又收到了 2流的3幀,再收到了3流的4幀,1流的2幀,1流的3幀,3流的5幀。
注意壁榕。相同的流之內(nèi),其幀必須是按順序的喳篇。
看一下下面的圖奏黑。還是之前的抓包圖
有沒有發(fā)現(xiàn)除了 0 幀之外蹂匹,為什么沒有偶數(shù)幀吊骤?1,3眷细,5 。鹃祖。溪椎。
這就是因?yàn)?由客戶端發(fā)起的連接,必須是奇數(shù)流恬口。服務(wù)端發(fā)起的必須是偶數(shù)流
一般服務(wù)端推送算作是服務(wù)端發(fā)起的連接校读,也就會(huì)出現(xiàn)偶數(shù)流了。
要想實(shí)現(xiàn)并發(fā)祖能,其實(shí)就是建立多個(gè)流歉秫。因?yàn)閱蝹€(gè)流因?yàn)楸仨氻樞虬l(fā)送,所以沒有辦法做到并發(fā)养铸。
- 流狀態(tài)管理的約束性規(guī)定
- 新建立的流ID必須大于曾經(jīng)建立過狀態(tài)為opened 或者 reserved 的流ID雁芙。
- 在新建立的流ID發(fā)送幀時(shí),意味著更小ID為idle的流就必須置為closed了钞螟。
- Stream ID 不能復(fù)用兔甘,長(zhǎng)連接耗盡的ID,只能通過重新建立TCP連接了筛圆。
Stream ID 為 0 的幀 是 控制幀裂明,如setting,window_update太援,ping等幀闽晦。