減少了網絡的來回時間,可以同時並且幾個TCP連接,如果太多的話,會加大服務器的壓力(D-DOS攻擊),各個瀏覽器會有自己想法,會考慮服務器的感受
采用頭部壓縮(字典)
二進制分幀層解決了隊頭阻塞,因為Http1.0發送的數據是有順序的,客戶端可以處理交錯的返回數據順序
多路復用允許單壹的 HTTP/2 連接同時發起多重的請求-響應消息。看個例子:
整個訪問流程第壹次請求index.html頁面,之後瀏覽器會去請求style.css和scripts.js的文件。左邊的圖是順序加載兩個個文件的,右邊則是 並行加載 兩個文件。
我們知道HTTP底層其實依賴的是TCP協議,那問題是在同壹個連接裏面同時發生兩個請求響應著是怎麽做到的?
首先妳要知道,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 裏面。
HTTP 性能優化的關鍵並不在於高帶寬,而是低延遲 。TCP 連接會隨著時間進行自我「調諧」,起初會限制連接的最大速度,如果數據成功傳輸,會隨著時間的推移提高傳輸的速度。這種調諧則被稱為 TCP 慢啟動。由於這種原因,讓原本就具有突發性和短時性的 HTTP 連接變的十分低效。
HTTP/2 通過讓所有數據流***用同壹個連接,可以更有效地使用 TCP 連接,讓高帶寬也能真正的服務於 HTTP 的性能提升。
通過下面兩張圖,我們可以更加深入的認識多路復用:
HTTP/1
HTTP/2
總結下:多路復用技術:單連接多資源的方式,減少服務端的鏈接壓力,內存占用更少,連接吞吐量更大;由於減少TCP 慢啟動時間,提高傳輸的速度
為什麽要壓縮?在 HTTP/1 中,HTTP 請求和響應都是由「狀態行、請求 / 響應頭部、消息主體」三部分組成。壹般而言,消息主體都會經過 gzip 壓縮,或者本身傳輸的就是壓縮過後的二進制文件(例如圖片、音頻),但狀態行和頭部卻沒有經過任何壓縮,直接以純文本傳輸。
隨著 Web 功能越來越復雜,每個頁面產生的請求數也越來越多,導致消耗在頭部的流量越來越多,尤其是每次都要傳輸 UserAgent、Cookie 這類 不會頻繁變動 的內容,完全是壹種浪費。
我們再用通俗的語言解釋下,壓縮的原理。頭部壓縮需要在支持 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,它允許服務端推送資源給瀏覽器,在瀏覽器明確地請求之前。壹個服務器經常知道壹個頁面需要很多附加資源,在它響應瀏覽器第壹個請求的時候,可以開始推送這些資源。這允許服務端去完全充分地利用壹個可能空閑的網絡,改善頁面加載時間。