HTTP/2 新特性淺析

HTTP發(fā)展簡(jiǎn)史

HTTP/0.9

  • 1991年發(fā)布
  • 只支持GET命令
  • 請(qǐng)求及返回值都是ASCII碼
  • 請(qǐng)求以換行符(CRLF)結(jié)束
  • 返回值只支持HTML格式
  • 服務(wù)器返回值之后立刻關(guān)閉連接
GET /index.html

HTTP/1.0

  • 1996年發(fā)布
  • 除了GET命令,還增加了POST和HEAD命令
  • 服務(wù)器支持返回任意格式
  • 請(qǐng)求和返回值除了包含數(shù)據(jù)部分圃阳,還增加頭部信息(HTTP header)
  • 返回值增加狀態(tài)碼(status code)
GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
HTTP/1.0 200 OK 
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84

<html>
  <body>Hello World</body>
</html>

HTTP/1.1

  • 1997年發(fā)布
  • 支持持久連接(Connection: keep-alive),即TCP連接默認(rèn)不關(guān)閉璧帝,可以被多個(gè)請(qǐng)求復(fù)用
  • 支持管道機(jī)制(pipelining)捍岳,即一個(gè)TCP連接內(nèi)可以同時(shí)發(fā)起多個(gè)請(qǐng)求
  • 支持分塊傳輸編碼(chunked transfer encoding)
  • 支持?jǐn)帱c(diǎn)續(xù)傳(Accept-Ranges)
  • 支持更多命令,如PUT, PATCH, OPTIONS, DELETE
  • 盡管支持復(fù)用TCP連接睬隶,但仍然會(huì)產(chǎn)生隊(duì)頭阻塞(Head-of-line blocking)問(wèn)題

HTTP/2

  • 2015年發(fā)布
  • 2009年Google自行研發(fā)的SPDY在Chrome上驗(yàn)證成功后锣夹,被當(dāng)作是HTTP/2的基礎(chǔ)
  • 完全采用二進(jìn)制協(xié)議
  • 支持多路復(fù)用(multiplexing)
  • 支持頭部壓縮(header compression)
  • 支持服務(wù)器推送(server push)

二進(jìn)制協(xié)議

HTTP/2之前的協(xié)議都是基于ASCII碼,好處是可讀性好苏潜,容易上手银萍。其缺點(diǎn)是可選的空格以及多變的終止符給識(shí)別幀造成了一些困難。采用二進(jìn)制協(xié)議可以使得幀的識(shí)別更簡(jiǎn)單恤左,并且傳輸信息更高效贴唇。其缺點(diǎn)是不便于調(diào)試,這就需要我們使用相應(yīng)的工具來(lái)理解二進(jìn)制的內(nèi)容赃梧。

HTTP/2完全采用二進(jìn)制協(xié)議滤蝠,頭信息和數(shù)據(jù)體都是二進(jìn)制的豌熄,統(tǒng)稱為(frame)授嘀。下圖展示了同一個(gè)請(qǐng)求在HTTP/1.1和HTTP/2的對(duì)應(yīng)關(guān)系,可見(jiàn)請(qǐng)求在HTTP/2中分為了兩部分:頭部幀和數(shù)據(jù)幀锣险。

一個(gè)幀的基本格式如下:

所有幀都由一個(gè)9字節(jié)的header和可變長(zhǎng)的payload組成蹄皱,各字段定義如下:

  • Length: 表示payload的長(zhǎng)度,payload的長(zhǎng)度默認(rèn)不能超過(guò)214 (16,384) 芯肤,除非修改SETTINGS_MAX_FRAME_SIZE為更大的值
  • Type: 表示幀的類型巷折,比如0x0表示數(shù)據(jù)幀,0x1表示頭部幀崖咨,類型不在規(guī)范里定義的幀將會(huì)被丟棄
  • Flags: 對(duì)于不同類型的幀锻拘,這個(gè)字段有不同的含義,比如在數(shù)據(jù)幀里击蹲,0x1表示這個(gè)frame是流的最后一幀(END_STREAM)
  • R: 保留位署拟,這一位必須置為0并且需要被忽略
  • Stream Identifier: 流ID,客戶端發(fā)起的流ID必須是奇數(shù)的歌豺,服務(wù)端發(fā)起的流ID必須是偶數(shù)的

多路復(fù)用

為了說(shuō)明什么是多路復(fù)用推穷,我們先需要明確下面幾個(gè)概念:

  • (stream): 已建立的連接內(nèi)的雙向字節(jié)流,可以承載一條或多條消息
  • 消息(message): 與邏輯請(qǐng)求或響應(yīng)消息對(duì)應(yīng)的完整的一系列幀
  • (frame): HTTP/2 通信的最小單位类咧,每個(gè)幀都包含幀頭馒铃,至少也會(huì)標(biāo)識(shí)出當(dāng)前幀所屬的數(shù)據(jù)流

這些概念的關(guān)系總結(jié)如下:

  • 所有通信都在一個(gè) TCP 連接上完成蟹腾,此連接可以承載任意數(shù)量的雙向數(shù)據(jù)流
  • 每個(gè)數(shù)據(jù)流都有一個(gè)唯一的標(biāo)識(shí)符和可選的優(yōu)先級(jí)信息,用于承載雙向消息
  • 每條消息都是一條邏輯 HTTP 消息(例如請(qǐng)求或響應(yīng))区宇,包含一個(gè)或多個(gè)幀
  • 幀是最小的通信單位娃殖,承載著特定類型的數(shù)據(jù),例如 HTTP Header议谷、消息負(fù)載等等珊随。 來(lái)自不同數(shù)據(jù)流的幀可以交錯(cuò)發(fā)送,然后再根據(jù)每個(gè)幀頭的數(shù)據(jù)流標(biāo)識(shí)符重新組裝

在HTTP/1.1中柿隙,如果客戶端為了提高性能想要在一個(gè)TCP連接內(nèi)同時(shí)發(fā)起多個(gè)請(qǐng)求叶洞,每個(gè)請(qǐng)求必須按順序被服務(wù)器依次響應(yīng),如果某一個(gè)請(qǐng)求特別耗時(shí)禀崖,那么后面的請(qǐng)求將會(huì)被一直阻塞衩辟。

而在HTTP/2中,如果在一個(gè)TCP連接內(nèi)同時(shí)發(fā)起多個(gè)請(qǐng)求波附,每個(gè)消息可以被拆成互不依賴的幀并且各幀之間交錯(cuò)發(fā)送艺晴,然后在另一端重新把幀組裝起來(lái)。這個(gè)特性就叫做多路復(fù)用掸屡。

上圖展示了同一個(gè)連接內(nèi)并行的多個(gè)數(shù)據(jù)流封寞。客戶端正在向服務(wù)器傳輸一個(gè)數(shù)據(jù)幀(數(shù)據(jù)流5)仅财,與此同時(shí)狈究,服務(wù)器正向客戶端交錯(cuò)發(fā)送數(shù)據(jù)流1和數(shù)據(jù)流3的一系列幀。因此盏求,一個(gè)連接上同時(shí)有三個(gè)并行數(shù)據(jù)流抖锥。

頭部壓縮

每個(gè)HTTP請(qǐng)求時(shí)都會(huì)承載一組表頭。在HTTP/1.x中表頭是以純文本形式傳輸碎罚,通常需要500~800字節(jié)的開(kāi)銷磅废,如果有cookie的話甚至?xí)_(dá)到上千字節(jié)。為了減少這種開(kāi)銷并且提升性能荆烈,HTTP/2使用了HPACK算法進(jìn)行壓縮拯勉,具體來(lái)說(shuō)包含了如下兩種簡(jiǎn)單并強(qiáng)大的技術(shù):

  • 頭部字段使用靜態(tài)Huffman編碼,如果編碼后使得字符反而變長(zhǎng)了憔购,那么不采用Huffman編碼
  • 客戶端和服務(wù)器同時(shí)維護(hù)并更新一個(gè)索引表宫峦,如果傳輸?shù)闹翟谒饕砝铮敲词褂盟饕底鳛閭鬏數(shù)闹稻胧肌K饕矸譃殪o態(tài)表和動(dòng)態(tài)表兩部分斗遏,靜態(tài)表在規(guī)范里定義,包含了一些常用的字段鞋邑,動(dòng)態(tài)表初始為空诵次,在連接過(guò)程中動(dòng)態(tài)更新

如上圖所示账蓉,最左邊是原始的請(qǐng)求頭,第一行的:method GET通過(guò)查找靜態(tài)索引表得到索引值為2逾一,所以HPACK算法將其編碼為2铸本。最后第二行的user-agent Mozilla/5.0 ...不在靜態(tài)索引表里,但在動(dòng)態(tài)索引表里查到索引值為62遵堵,所以HPACK算法將其編碼為62箱玷。最后一行的兩個(gè)字段均未在索引表里查到,所以分別對(duì)其進(jìn)行Huffman編碼陌宿。

服務(wù)器推送

HTTP/2新增的另一個(gè)強(qiáng)大的功能是允許服務(wù)器除了可以響應(yīng)客戶端請(qǐng)求锡足,還可以向客戶端推送額外的資源。

通常當(dāng)我們請(qǐng)求一個(gè)網(wǎng)頁(yè)時(shí)壳坪,客戶端解析HTML源碼舶得,發(fā)現(xiàn)有js或css等其他靜態(tài)資源,然后再發(fā)起請(qǐng)求下載靜態(tài)資源爽蝴。而實(shí)際上沐批,當(dāng)客戶端請(qǐng)求網(wǎng)頁(yè)后,服務(wù)器完全可以預(yù)判客戶端接下來(lái)要請(qǐng)求相關(guān)的靜態(tài)資源蝎亚,那為什么不讓服務(wù)器提前推送這些資源九孩,從而減少額外的延遲時(shí)間呢?HTTP/2為此提出了服務(wù)器推送機(jī)制发框,服務(wù)器端可以通過(guò)發(fā)起PUSH_PROMISE幀告知客戶端躺彬,客戶端收到服務(wù)器想要推送資源的意圖后,可以決定是否接收推送缤底。

事實(shí)上顾患,如果你在網(wǎng)頁(yè)中內(nèi)聯(lián)CSS或Javascript,那么你已經(jīng)體驗(yàn)過(guò)服務(wù)器推送了个唧。使用HTTP/2,我們不僅可以獲得相同效果设预,還可以獲得更多的性能優(yōu)勢(shì):

  • 客戶端可以緩存推送資源
  • 推送資源可以被不同頁(yè)面重用
  • 推送資源可以與其他資源復(fù)用
  • 推送資源可以由服務(wù)器設(shè)定優(yōu)先級(jí)
  • 推送資源可以被客戶端拒絕(非強(qiáng)制推送)

服務(wù)器推送功能雖然很強(qiáng)大徙歼,但在實(shí)際使用中還需要考慮一些問(wèn)題。第一個(gè)問(wèn)題是如果客戶端已經(jīng)有緩存了鳖枕,那么推送資源就是一種浪費(fèi)魄梯。一種解決方法是只在用戶第一次訪問(wèn)的時(shí)候推送資源。第二個(gè)問(wèn)題是目前我們一般把靜態(tài)資源放在CDN上宾符,目前大部分CDN還不支持服務(wù)器推送酿秸,那么CDN和服務(wù)器推送到底哪個(gè)效果更好,這個(gè)可能還需要一些測(cè)試數(shù)據(jù)來(lái)做評(píng)判魏烫。

參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末辣苏,一起剝皮案震驚了整個(gè)濱河市肝箱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌稀蟋,老刑警劉巖煌张,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異退客,居然都是意外死亡骏融,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門萌狂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)档玻,“玉大人,你說(shuō)我怎么就攤上這事茫藏∏猿Γ” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵刷允,是天一觀的道長(zhǎng)冤留。 經(jīng)常有香客問(wèn)我,道長(zhǎng)树灶,這世上最難降的妖魔是什么纤怒? 我笑而不...
    開(kāi)封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任痘煤,我火速辦了婚禮瓣蛀,結(jié)果婚禮上故爵,老公的妹妹穿的比我還像新娘检柬。我一直安慰自己茫多,他們只是感情好料扰,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布喂江。 她就那樣靜靜地躺著胆敞,像睡著了一般诺祸。 火紅的嫁衣襯著肌膚如雪携悯。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天筷笨,我揣著相機(jī)與錄音憔鬼,去河邊找鬼。 笑死胃夏,一個(gè)胖子當(dāng)著我的面吹牛轴或,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仰禀,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼照雁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了答恶?” 一聲冷哼從身側(cè)響起饺蚊,我...
    開(kāi)封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤萍诱,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后卸勺,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體砂沛,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年曙求,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了碍庵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡悟狱,死狀恐怖静浴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挤渐,我是刑警寧澤苹享,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站浴麻,受9級(jí)特大地震影響得问,放射性物質(zhì)發(fā)生泄漏软免。R本人自食惡果不足惜宫纬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一膏萧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧榛泛,春花似錦蝌蹂、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)艘希。三九已至硼身,卻和暖如春覆享,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背营袜。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工撒顿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荚板。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓吩屹,卻偏偏與公主長(zhǎng)得像拧抖,于是被迫代替她去往敵國(guó)和親煤搜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子唧席,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容