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

三、HTTP 2.0 vs HTTP 1.0 效能
HTTP 2.0 的出現,相比於 HTTP 1.x ,大幅度的提升了 web 效能。

這是 Akamai 公司建立的一個官方的演示,用以說明 HTTP/2 相比於之前的 HTTP/1.1 在效能上的大幅度提升。 同時請求 379 張圖片,從Load time 的對比可以看出 HTTP/2 在速度上的優勢。
四、HTTP 2.0 和 HTTP1.1 區別
後面我們將通過幾個方面來說說HTTP 2.0 和 HTTP1.1 區別,並且和你解釋下其中的原理。
ofollow,noindex">區別一:多路複用
多路複用允許單一的 HTTP/2 連線同時發起多重的請求-響應訊息。看個例子:

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

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

在二進位制分幀層中, HTTP/2 會將所有傳輸的資訊分割為幀(frame),並對它們採用二進位制格式的編碼 ,其中 首部資訊會被封裝到 HEADER frame,而相應的 Request Body 則封裝到 DATA frame 裡面。掌握這 11 個方法論 ,搞定一場完美技術面試!
HTTP 效能優化的 關鍵並不在於高頻寬,而是低延遲 。TCP 連線會隨著時間進行自我「調諧」,起初會限制連線的最大速度,如果資料成功傳輸,會隨著時間的推移提高傳輸的速度。這種調諧則被稱為 TCP 慢啟動。由於這種原因,讓原本就具有突發性和短時性的 HTTP 連線變的十分低效。
HTTP/2 通過讓所有資料流共用同一個連線,可以更有效地使用 TCP 連線,讓高頻寬也能真正的服務於 HTTP 的效能提升。
通過下面兩張圖,我們可以更加深入的認識多路複用:

HTTP/1

HTTP/2
總結下:多路複用技術:單連線多資源的方式,減少服務端的連結壓力,記憶體佔用更少,連線吞吐量更大;由於減少TCP 慢啟動時間,提高傳輸的速度
區別二:首部壓縮
為什麼要壓縮?在 HTTP/1 中,HTTP 請求和響應都是由「狀態行、請求 / 響應頭部、訊息主體」三部分組成。一般而言,訊息主體都會經過 gzip 壓縮,或者本身傳輸的就是壓縮過後的二進位制檔案(例如圖片、音訊),但狀態行和頭部卻沒有經過任何壓縮,直接以純文字傳輸。
隨著 Web 功能越來越複雜,每個頁面產生的請求數也越來越多,導致消耗在頭部的流量越來越多,尤其是每次都要傳輸 UserAgent、Cookie 這類不會頻繁變動的內容,完全是一種浪費。掌握這 11 個方法論 ,搞定一場完美技術面試!
我們再用通俗的語言解釋下,壓縮的原理。頭部壓縮需要在支援 HTTP/2 的瀏覽器和服務端之間。
維護一份相同的靜態字典(Static Table),包含常見的頭部名稱,以及特別常見的頭部名稱與值的組合;
維護一份相同的動態字典(Dynamic Table),可以動態的新增內容;
支援基於靜態哈夫曼碼錶的哈夫曼編碼(Huffman Coding);
靜態字典的作用有兩個:
1)對於完全匹配的頭部鍵值對,例如 “:method :GET”,可以直接使用一個字元表示;
2)對於頭部名稱可以匹配的鍵值對,例如 “cookie :xxxxxxx”,可以將名稱使用一個字元表示。
HTTP/2 中的靜態字典如下(以下只截取了部分,完整表格在這裡):

同時,瀏覽器和服務端都可以向動態字典中新增鍵值對,之後這個鍵值對就可以使用一個字元表示了。需要注意的是,動態字典上下文有關,需要為每個 HTTP/2 連線維護不同的字典。在傳輸過程中使用,使用字元代替鍵值對大大減少傳輸的資料量。
服務端推送是一種在客戶端請求之前傳送資料的機制。當代網頁使用了許多資源:HTML、樣式表、指令碼、圖片等等。在HTTP/1.x中這些資源每一個都必須明確地請求。這可能是一個很慢的過程。瀏覽器從獲取HTML開始,然後在它解析和評估頁面的時候,增量地獲取更多的資源。因為伺服器必須等待瀏覽器做每一個請求,網路經常是空閒的和未充分使用的。
為了改善延遲,HTTP/2引入了server push,它允許服務端推送資源給瀏覽器,在瀏覽器明確地請求之前。一個伺服器經常知道一個頁面需要很多附加資源,在它響應瀏覽器第一個請求的時候,可以開始推送這些資源。這允許服務端去完全充分地利用一個可能空閒的網路,改善頁面載入時間。
