前言
HTTP2.0大幅度的提高了web效能,在HTTP1.1完全語意相容的基礎上,進一步減少了網路的延遲。實現低延遲高吞吐量。對於前端開發者而言,減少了優化工作。本文將重點圍繞以下幾點新特性的作用、工作過程以及如何更出色的完成了優化工作來介紹HTTP2.0
- 二進位制分幀
- 首部壓縮
- 流量控制
- 多路複用
- 請求優先順序
- 伺服器推送
二進位制分幀
在不改變HTTP1.x的語義、方法、狀態碼。URL以及首部欄位的情況下,HTTP2.0是怎樣突破HTTP1.1的效能限制,改進傳輸效能,實現低延遲高吞吐量的呢?關鍵之一就是在應用層(HTTP)和傳輸層(TCP)之間增加一個二進位制分幀層。
在整理二進位制分幀及其作用的時候我們先來鋪墊一點關於幀的知識:
- 幀:HTTP2.0通訊的最小單位,所有幀都共享一個8位元組的首部,其中包含幀的長度、型別、標誌、還有一個保留位,並且至少有標識出當前幀所屬的流的識別符號,幀承載著特定型別的資料,如HTTP首部、負荷、等等。
- 訊息:比幀大的通訊單位,是指邏輯上的HTTP訊息,比如請求、響應等。由一個或多個幀組成
- 流:比訊息大的通訊單位。是TCP連線中的一個虛擬通道,可以承載雙向的訊息。每個流都有一個唯一的整數識別符號
什麼是二進位制分幀
在二進位制分幀層上,HTTP2.0會將所有傳輸資訊分割為更小的訊息和幀,並對它們採用二進位制格式的編碼將其封裝。其中,HTTP1.X中的首部資訊header封裝到Headers幀中,而request body將被封裝到Data幀中。
二進位制分幀如何工作
HTTP2.0通訊都在一個TCP連線上完成,這個連線可以承載任意數量的雙向資料流,相應的每個資料流以訊息的形式傳送。而訊息由一或多個幀組成,這些幀可以亂序傳送,然後根據每個幀首部的流識別符號重新組裝。
二進位制分幀對效能優化工作的貢獻
二進位制分幀主要是為下文中的各種特性提供了基礎。它能把一個資料劃分封裝為更小更便捷的資料。首先是在單連結多資源方式中,減少了服務端的連結壓力,記憶體佔用更少,連結吞吐量更大。這一點可以結合下文中的多路複用來體會。另一方面,由於TCP連結的減少而使網路擁塞狀態得以改善,同時慢啟動時間的減少。使擁塞和丟包恢復的速度更快。
首部壓縮
HTTP1.1並不支援HTTP首部壓縮,為此SPDY和HTTP2.0出現了。SPDY是用的是DEFLATE演算法,而HTTP2.0則使用了專門為首部壓縮設計的HPACK演算法。
什麼是首部壓縮
HTTP1.x每次通訊(請求或響應)都會攜帶首部資訊用於描述資源屬性。而HTTP2.0在客戶端和服務端之間使用首部表來跟蹤和儲存之前傳送的鍵值對。請求與響應首部的定義在HTTP2.0中基本沒有變,只是所有首部鍵必須全部小寫,而且要求行要獨立為:method:、:scheme:、:host:、:path:這些鍵值對
首部壓縮如何工作
對於相同的資料,不再重新通過每次請求和響應傳送。每個新的首部鍵值對要麼追加到當前表的末尾,要麼替換表中之前的值。首部表在HTTP2.0的連結存續期內始終存在,由客戶端和服務端共同漸進的更新。
首部壓縮效能優化工作的貢獻
首部表在HTTP2.0使用了首部壓縮的技術。使報頭更緊湊,更快速傳輸,有利於行動網路環境。減少每次通訊的資料量,使網路擁塞狀態得以改善。
流量控制
HTTP2.0為資料流和連線的流量提供了一個簡單的機制:
- 流量基於HTTP連結的每一跳進行,而非端到端的控制
- 流量控制基於視窗更新幀進行,即接收方廣播自己準備接收某個資料流的多少位元組,以及對整個連結要接收多少個位元組。
- 流量控制有方向性,即接收方可能根據自己的情況為沒個流乃至整個連結設定任意視窗大小
- 流量控制可以由接收方禁用,包括針對個別的流和針對整個連結。
- 幀的型別決定了流量控制是否適用於幀,目前只有DATA幀服從流量控制,所有其他型別的幀並不會消耗流量控制視窗的空間。這保證了重要的控制幀不會被流量控制阻塞
多路複用
在HTTP1.1中,瀏覽器客戶端在同一時間,針對同一域名下的請求有一定數量的限制。超過限制數目的請求會被阻塞。而HTTP2.0中的多路複用優化了這一效能。
什麼是多路複用
基於二進位制分幀層,HTTP2.0可以在共享TCP連結的基礎上同時傳送請求和響應。HTTP訊息被分解為獨立的幀,而不破壞訊息本身的語義,交錯發出去,在另一端根據流識別符號和首部將他們重新組裝起來。
多路複用如何工作
我們來通過與HTTP1.X的對比來看看他是如何工作的。
- HTTP1.x
- HTTP2.0
多路複用對效能優化工作的貢獻
- 可以並行交錯的傳送請求和響應,這些請求和響應之間互不影響
- 只使用一個連結即可並行傳送多個請求和響應
- 消除不必要的延遲,從而減少頁面載入的時間
- 不必再為繞過HTTP1.x限制而多做很多工作
請求優先順序
把HTTP訊息分為很多獨立幀之後,就可以通過優化這些幀的交錯和傳輸順序進一步優化效能。
什麼是請求優先順序
每個流都可以帶有一個31bit的優先值:0表示最高優先順序;2的31次方-1表示最低優先順序。
請求優先順序如何工作
客戶端明確指定優先順序,服務端可以根據這個優先順序作為互動資料的依據,比如客戶端優先設定為.css>.js>.jpg。服務端按此順序返回結果更加有利於高效利用底層連線,提高使用者體驗。然而,在使用請求優先順序時應注意服務端是否支援請求優先順序,是否會引起隊首阻塞問題,比如高優先順序的慢響應請求會阻塞其他資源的互動。
請求優先順序對效能優化工作的貢獻
伺服器可以根據流的優先順序控制資源分配(CPU、記憶體、寬頻),而在響應資料準備好之後,優先將最高優先順序的幀傳送給客戶端。瀏覽器可以在發現資源時立即分派請求,指定每個流的優先順序,讓伺服器決定最優的響應次序。這樣請求就不用排隊了,既節省了時間,又最大限度的利用了每個連線。
伺服器推送
HTTP2.0新增的一個強大的新功能,就是伺服器可以對一個客戶端請求傳送多個響應。伺服器向客戶端推送資源無需客戶端明確的請求。
什麼是伺服器推送(HTTP2.0中)
服務端根據客戶端的請求,提前返回多個響應,推送額外的資源給客戶端。如下圖,客戶端請求stream 1(/page.html)。服務端在返回stream 1的訊息的同時推送了stream 2(/script.js)和stream 4(/style.css)
伺服器推送如何工作
- PUSH_PROMISE幀是服務端向客戶端有意推送資源的訊號。
- PUSH_PROMISE幀中只包含預推送資源的首部。如果客戶端對PUSH_PROMISE幀沒有意見,服務端在PUSH_PROMISE幀後傳送響應的DATA幀。如果客戶端已經快取了該資源,不需要推送,可以拒絕PUSH_PROMISE幀。
- PUSH-PROMISE必須遵循請求-響應原則,只能藉著對請求的響應推送資源。
- PUSH_PROMISE幀必須在返回響應之前傳送,以免客戶端出現競態條件(競態條件是指在多執行緒的情況下不同的執行順序會導致計算機執行出不同的結果正確性不同)
- HTTP2.0連線後,客戶端與服務端交換SETTINGS幀,藉此限定雙向併發的最大數量。因此,客戶端可以限定推送流的數量,或者通過把這個只設定為0來完全禁止伺服器推送。
- 所有推送的資源都必須遵守同源策略。換句話說,伺服器不能隨便將第三方資源推送給客戶端,而必須是經過雙方的確認才行。
伺服器推送對效能優化工作的貢獻
服務端推送是一種在客戶端請求之前傳送資料的機制。在HTTP2.0中,伺服器可以對一個客戶端的請求傳送多個響應。如果一個請求是由你的主頁傳送的,伺服器可能會響應主頁內容、logo以及樣式表,因為他知道客戶端會用到這些東西。這樣不但減輕了資料傳送冗餘步驟,也加快了頁面響應的速度,提高了使用者體驗。