http/2 學(xué)習(xí)筆記

http/2 學(xué)習(xí)

自己對(duì)于http/2 的理解還停留在面試死記硬背的水平,所以最近對(duì)自己心中一些疑問以及自己的理解做一個(gè)總結(jié),這些總結(jié)可能會(huì)有錯(cuò)誤。如果有大佬覺得哪里有什么問題,可以直接說出。

http/2 的完整介紹很多。珠玉在前:http/2 簡(jiǎn)介 ,就不在贅述了。

問題一: http/2 為什么要使用二進(jìn)制分幀層

二進(jìn)制協(xié)議的理解:

對(duì)于這個(gè)問題,我們首先就要搞清楚什么http1.1的文本協(xié)議和htt/p2的二進(jìn)制協(xié)議的不同了。其實(shí)我作為一個(gè)基礎(chǔ)并不牢固的搬磚工,當(dāng)看到這個(gè)二進(jìn)制的時(shí)候我就在想:在計(jì)算機(jī)世界當(dāng)中所有的內(nèi)容不都是二進(jìn)制嗎?為什么還要有二進(jìn)制以及文本協(xié)議之分呢?

帶著這個(gè)問題,我在網(wǎng)上找到了一些回復(fù),就直接搬下來吧

Binary protocol versus text protocol isn't really about how binary blobs are encoded. The difference is really whether the protocol is oriented around data structures or around text strings. Let me give an example: HTTP. HTTP is a text protocol, even though when it sends a jpeg image, it just sends the raw bytes, not a text encoding of them.

四級(jí)低空略過水平的翻譯:

二進(jìn)制協(xié)議和文本協(xié)議的區(qū)別并不是關(guān)于二進(jìn)制blob是如何編碼的。關(guān)鍵在于協(xié)議是以數(shù)據(jù)結(jié)構(gòu)為導(dǎo)向還是以文本字符串為導(dǎo)向。

文本協(xié)議請(qǐng)求:其中所有的內(nèi)容都是文字

[圖片上傳失敗...(image-8fb482-1614501899169)]

二進(jìn)制請(qǐng)求:

struct request {
  int requestType;
  int protocolVersion;
  char path[1024];
  char user_agent[1024];
  char host[1024];
  long int accept_bitmask;
  long int language_bitmask;
  long int charset_bitmask;
};

當(dāng)我們看到http文本協(xié)議以及二進(jìn)制請(qǐng)求的結(jié)構(gòu)之后:

  • 二進(jìn)制協(xié)議比文本協(xié)議更加緊湊。
  • 文本協(xié)議解析是需要特殊字符的,比如\r\n,一方面造成了文本協(xié)議更加冗長(zhǎng),另一方面使用這種特殊字符解析一段文字的方式,沒有二進(jìn)制解析方便快捷。
  • 二進(jìn)制協(xié)議中的數(shù)字比文本中的數(shù)字占用空間更?。罕热鏷ttp中狀態(tài)碼200,在文本協(xié)議中是 "2" "0" "0",這三個(gè)數(shù)字要分別用編碼表示的,但是在二進(jìn)制協(xié)議中,不用將數(shù)字編碼成文本格式,直接用二進(jìn)制表示數(shù)字就可以了: 11001000 。

http/2中的二進(jìn)制分幀層

參考文章

At the core of all performance enhancements of HTTP/2 is the new binary framing layer, which dictates how the HTTP messages are encapsulated and transferred between the client and server.

_
在許多文章中,都說http/2中的二進(jìn)制分幀層,是http/2性能提升的關(guān)鍵,它給一個(gè)tcp鏈接同時(shí)發(fā)送多個(gè)請(qǐng)求提供了可能。

http.png

HTTP/1.1和HTTP/2都是基于TCP的協(xié)議,TCP模型是雙向數(shù)據(jù)流,任何在一個(gè)TCP連接上處理超過一個(gè)請(qǐng)求的協(xié)議都需要解決這樣兩個(gè)問題:

  1. 分片——如何將流中的多個(gè)請(qǐng)求和響應(yīng)拆分成獨(dú)立的消息
  2. 對(duì)應(yīng)——如何將請(qǐng)求和響應(yīng)對(duì)應(yīng)起來

在這兩個(gè)問題中,我覺得第二個(gè)往往會(huì)讓人忽略,就是在http1.1 中,一個(gè)tcp請(qǐng)求只能同時(shí)完成一個(gè)請(qǐng)求響應(yīng)過程,所以請(qǐng)求以及響應(yīng)天生一一對(duì)應(yīng),不存在響應(yīng)和請(qǐng)求無法匹配的問題。但是當(dāng)我們打開抓包工具查看相應(yīng)的相關(guān)http報(bào)文的時(shí)候,會(huì)發(fā)現(xiàn)其實(shí)響應(yīng)是沒有一個(gè)字段去和請(qǐng)求一一對(duì)應(yīng)的。這就給http/2的多路復(fù)用帶來了問題,一個(gè)tcp連接中多個(gè)請(qǐng)求,多個(gè)響應(yīng),那么如何將這些響應(yīng)和請(qǐng)求一一對(duì)應(yīng)呢?只能在二進(jìn)制分幀層添加字段了,所以在http/2幀的報(bào)文格式中,有一個(gè)字段是Stream Identifier,這個(gè)流ID可以將響應(yīng)和請(qǐng)求一一對(duì)應(yīng)。這個(gè)根本解決了多路復(fù)用,請(qǐng)求以及響應(yīng)匹配的問題。

所以給這個(gè)問題來一個(gè)總結(jié)吧:

  • 二進(jìn)制協(xié)議比文本協(xié)議更加緊湊,減少占用空間。
  • 分幀層相當(dāng)于將http切分,更加靈活,比如可以對(duì)header幀做單獨(dú)的特殊處理。
  • 分幀層有著屬于自己的報(bào)文頭,其中的Stream Identifier 使得操作系統(tǒng)具備將多個(gè)響應(yīng)以及請(qǐng)求一一匹配的能力,這個(gè)是http/2 性能提升的關(guān)鍵,也就是多路復(fù)用。
  • 二進(jìn)制分幀層存在的意義是將請(qǐng)求或響應(yīng)切分,可以更加靈活處理。分幀層定義的報(bào)文格式,例如Stream Identifier等,直接關(guān)乎http/2 的各種優(yōu)化方案的實(shí)現(xiàn)。

問題二:tcp與http/2的幀的關(guān)系

在http/2中幀是最小通信單位,我的問題是http/2 中的幀和最小的tcp數(shù)據(jù)包是什么關(guān)系,一一對(duì)應(yīng)的嗎?在http/2 的請(qǐng)求中,tcp是如何拆分以及組裝消息的?

很多面試題中多路復(fù)用的解釋

其中的解釋如下:

  • 同域名下所有通信都在單個(gè)連接上完成,消除了因多個(gè) TCP 連接而帶來的延時(shí)和內(nèi)存消耗。
  • 單個(gè)連接上可以并行交錯(cuò)的請(qǐng)求和響應(yīng),之間互不干擾

下面的解釋當(dāng)中,并行交錯(cuò)的請(qǐng)求和響應(yīng)。其實(shí)這個(gè)并行請(qǐng)求應(yīng)該具體為并行http請(qǐng)求,那么tcp可以將請(qǐng)求拆分并行請(qǐng)求嗎?

這個(gè)就要從tcp如何組裝以分拆http報(bào)文說起了,

TCP 數(shù)據(jù)包在 IP 數(shù)據(jù)包的負(fù)載里面。它的頭信息最少也需要20字節(jié),因此 TCP 數(shù)據(jù)包的最大負(fù)載是 1480 - 20 = 1460 字節(jié)。由于 IP 和 TCP 協(xié)議往往有額外的頭信息,所以 TCP 負(fù)載實(shí)際為1400字節(jié)左右。因此,一條1500字節(jié)的信息需要兩個(gè) TCP 數(shù)據(jù)包

我們假設(shè)有兩個(gè)post請(qǐng)求并行進(jìn)行請(qǐng)求:

截屏2021-02-27 上午10.32.35.png
截屏2021-02-27 上午10.32.35.png

如果TCP協(xié)議層面并行請(qǐng)求,并將順序打亂,這樣可以嗎?


截屏2021-02-27 上午10.22.02.png
截屏2021-02-27 上午10.22.02.png

在我看來其實(shí)這是不可以的,因?yàn)閠cp協(xié)議是完全按照順序組裝數(shù)據(jù)包的,如果并行請(qǐng)求并將數(shù)據(jù)包順序打亂,那么計(jì)算機(jī)將不知道如何組裝這些數(shù)據(jù)包。

所以上面的并行請(qǐng)求是不準(zhǔn)確的,在計(jì)算機(jī)內(nèi)部一定是串行請(qǐng)求,發(fā)完一個(gè)請(qǐng)求的數(shù)據(jù)包,在發(fā)送下一個(gè)請(qǐng)求的數(shù)據(jù)包,這樣才能保證數(shù)據(jù)包組合正確。

所以http/2中的幀,是按照順序串行請(qǐng)求的,如果不是這樣,數(shù)據(jù)將無從組裝,一一對(duì)應(yīng)。


截屏2021-02-27 上午10.30.21.png
截屏2021-02-27 上午10.30.21.png

總結(jié)一下吧:

  • http/2中的幀是最小通信單位,但這僅僅是在http/2這一協(xié)議層。一個(gè)http/2中的幀,如果信息過多,可能是由多個(gè)tcp拆分組成,所以http/2中的幀概念,并不是一一對(duì)應(yīng)網(wǎng)絡(luò)協(xié)議中的一個(gè)數(shù)據(jù)包。
  • 一個(gè)或多個(gè)tcp報(bào)文組成一個(gè)幀,一個(gè)或多個(gè)幀組成一個(gè)http/2的請(qǐng)求或者響應(yīng)。
  • http/2 一個(gè)tcp鏈接不存在并行傳輸,是串行傳輸,發(fā)送完一個(gè)幀的數(shù)據(jù)包,再發(fā)送下一個(gè)幀的相關(guān)數(shù)據(jù)包。

如果有哪些地方理解不到位,請(qǐng)不吝賜教

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容