讓面試官顫抖的 HTTP 2.0 協(xié)議面試題
Http協(xié)議,對于擁有豐富開發(fā)經(jīng)驗的程序員來說簡直是信手拈來,家常便飯。雖然天天見,但是對于http協(xié)議的問題,可能很多人在沒有積極準備的情況下,不一定能很好的回答出來。
今天,我們就來講講http 2.0和之前版本的區(qū)別。
一、HTTP定義
HTTP協(xié)議(HyperTextTransferProtocol,超文本傳輸協(xié)議)是用于從WWW服務(wù)器傳輸超文本到本地瀏覽器的傳輸協(xié)議。
二、HTTP發(fā)展史

三、HTTP 2.0 vs 1.0 性能
HTTP 2.0 的出現(xiàn),相比于 HTTP 1.x ,大幅度的提升了 web 性能。

這是 Akamai 公司建立的一個官方的演示,用以說明 HTTP/2 相比于之前的 HTTP/1.1 在性能上的大幅度提升。 同時請求 379 張圖片,從Load time 的對比可以看出 HTTP/2 在速度上的優(yōu)勢。
四、HTTP 2.0 和 1.1 區(qū)別
后面我們將通過幾個方面來說說HTTP 2.0 和 HTTP1.1 區(qū)別,并且和你解釋下其中的原理。
區(qū)別一:多路復用
多路復用允許單一的 HTTP/2 連接同時發(fā)起多重的請求-響應消息。看個例子:

整個訪問流程第一次請求index.html頁面,之后瀏覽器會去請求style.css和scripts.js的文件。左邊的圖是順序加載兩個個文件的,右邊則是并行加載兩個文件。
我們知道HTTP底層其實依賴的是TCP協(xié)議,那問題是在同一個連接里面同時發(fā)生兩個請求響應著是怎么做到的?
首先你要知道,TCP連接相當于兩根管道(一個用于服務(wù)器到客戶端,一個用于客戶端到服務(wù)器),管道里面數(shù)據(jù)傳輸是通過字節(jié)碼傳輸,傳輸是有序的,每個字節(jié)都是一個一個來傳輸。
例如客戶端要向服務(wù)器發(fā)送Hello、World兩個單詞,只能是先發(fā)送Hello再發(fā)送World,沒辦法同時發(fā)送這兩個單詞。不然服務(wù)器收到的可能就是HWeolrllod(注意是穿插著發(fā)過去了,但是順序還是不會亂)。這樣服務(wù)器就懵b了。
接上面的問題,能否同時發(fā)送Hello和World兩個單詞能,當然也是可以的,可以將數(shù)據(jù)拆成包,給每個包打上標簽。發(fā)的時候是這樣的①H ②W ①e ②o ①l ②r ①l ②l ①o ②d。這樣到了服務(wù)器,服務(wù)器根據(jù)標簽把兩個單詞區(qū)分開來。實際的發(fā)送效果如下圖:

要實現(xiàn)上面的效果我們引入一個新的概念就是:二進制分幀。
二進制分幀層 在 應用層(HTTP/2)和傳輸層(TCP or UDP)之間。HTTP/2并沒有去修改TCP協(xié)議而是盡可能的利用TCP的特性。

在二進制分幀層中, HTTP/2 會將所有傳輸?shù)男畔⒎指顬閹?frame),并對它們采用二進制格式的編碼 ,其中 首部信息會被封裝到 HEADER frame,而相應的 Request Body 則封裝到 DATA frame 里面。
HTTP 性能優(yōu)化的關(guān)鍵并不在于高帶寬,而是低延遲。TCP 連接會隨著時間進行自我「調(diào)諧」,起初會限制連接的最大速度,如果數(shù)據(jù)成功傳輸,會隨著時間的推移提高傳輸?shù)乃俣?。這種調(diào)諧則被稱為 TCP 慢啟動。由于這種原因,讓原本就具有突發(fā)性和短時性的 HTTP 連接變的十分低效。
HTTP/2 通過讓所有數(shù)據(jù)流共用同一個連接,可以更有效地使用 TCP 連接,讓高帶寬也能真正的服務(wù)于 HTTP 的性能提升。
通過下面兩張圖,我們可以更加深入的認識多路復用:

HTTP/1

HTTP/2
總結(jié)下:多路復用技術(shù):單連接多資源的方式,減少服務(wù)端的鏈接壓力,內(nèi)存占用更少,連接吞吐量更大;由于減少TCP 慢啟動時間,提高傳輸?shù)乃俣取?/p>
區(qū)別二:首部壓縮
為什么要壓縮?在 HTTP/1 中,HTTP 請求和響應都是由「狀態(tài)行、請求 / 響應頭部、消息主體」三部分組成。一般而言,消息主體都會經(jīng)過 gzip 壓縮,或者本身傳輸?shù)木褪菈嚎s過后的二進制文件(例如圖片、音頻),但狀態(tài)行和頭部卻沒有經(jīng)過任何壓縮,直接以純文本傳輸。
隨著 Web 功能越來越復雜,每個頁面產(chǎn)生的請求數(shù)也越來越多,導致消耗在頭部的流量越來越多,尤其是每次都要傳輸 UserAgent、Cookie 這類不會頻繁變動的內(nèi)容,完全是一種浪費。
我們再用通俗的語言解釋下,壓縮的原理。頭部壓縮需要在支持 HTTP/2 的瀏覽器和服務(wù)端之間。
- 維護一份相同的靜態(tài)字典(Static Table),包含常見的頭部名稱,以及特別常見的頭部名稱與值的組合;
- 維護一份相同的動態(tài)字典(Dynamic Table),可以動態(tài)的添加內(nèi)容;
- 支持基于靜態(tài)哈夫曼碼表的哈夫曼編碼(Huffman Coding);
靜態(tài)字典的作用有兩個:
- 對于完全匹配的頭部鍵值對,例如 “:method :GET”,可以直接使用一個字符表示;
- 對于頭部名稱可以匹配的鍵值對,例如 “cookie :xxxxxxx”,可以將名稱使用一個字符表示。
HTTP/2 中的靜態(tài)字典如下(以下只截取了部分,完整表格在這里):

同時,瀏覽器和服務(wù)端都可以向動態(tài)字典中添加鍵值對,之后這個鍵值對就可以使用一個字符表示了。需要注意的是,動態(tài)字典上下文有關(guān),需要為每個 HTTP/2 連接維護不同的字典。在傳輸過程中使用,使用字符代替鍵值對大大減少傳輸?shù)臄?shù)據(jù)量。
區(qū)別三:HTTP2支持服務(wù)器推送
服務(wù)端推送是一種在客戶端請求之前發(fā)送數(shù)據(jù)的機制。當代網(wǎng)頁使用了許多資源:HTML、樣式表、腳本、圖片等等。在HTTP/1.x中這些資源每一個都必須明確地請求。這可能是一個很慢的過程。瀏覽器從獲取HTML開始,然后在它解析和評估頁面的時候,增量地獲取更多的資源。因為服務(wù)器必須等待瀏覽器做每一個請求,網(wǎng)絡(luò)經(jīng)常是空閑的和未充分使用的。
為了改善延遲,HTTP/2引入了server push,它允許服務(wù)端推送資源給瀏覽器,在瀏覽器明確地請求之前。一個服務(wù)器經(jīng)常知道一個頁面需要很多附加資源,在它響應瀏覽器第一個請求的時候,可以開始推送這些資源。這允許服務(wù)端去完全充分地利用一個可能空閑的網(wǎng)絡(luò),改善頁面加載時間。
