HTTP/2協議–特性掃盲篇

 

HTTP/2協議–特性掃盲篇

隨着web技術的飛速發展,1999年制定的HTTP 1.1已經沒法知足你們對性能的要求,Google推出協議SPDY,旨在解決HTTP 1.1中廣爲人知的性能問題。SPDY獲得了Chrome、Firefox和Opera的支持,不少大型網站(如谷歌、Twitter、Facebook、淘寶)都對兼容客戶端使用SPDY。SPDY在被行業採用並證實可以大幅提高性能以後,已經具有了成爲一個標準的條件。html

HTTP工做組採用了SPDY v2草案做爲制定HTTP 2.0標準的起點,2014年12月將HTTP/2標準提議遞交至IESG進行討論,於2015年2月17日被批准。HTTP/2標準於2015年5月以RFC 7540正式發表。至此,SPDY完成了歷史的使命,即將退出歷史的舞臺,HTTP/2粉墨登場。git

在HTTP的語義、HTTP方法、狀態碼、URI和首部字段等核心概念不變的狀況下,HTTP/2實現了性能優化,HTTP/2具體有哪些變化呢?下面一一解答 O(∩_∩)O~github

二進制分幀(Binary Framing)

HTTP1.x以換行符做爲純文本的分隔符。web

HTTP/2將全部傳輸的信息分割爲更小的消息和幀,並對它們採用二進制格式的編碼,咱們先了解幾個概念:瀏覽器

  • 幀(Frame):HTTP/2通訊的最小單位,每一個幀包含幀首部,至少也會標識出當前幀所屬的流。
  • 消息(Message):由一個或多個幀組合而成,例如請求和響應。
  • 鏈接(Connection):與 HTTP/1 相同,都是指對應的 TCP 鏈接;
  • 流(Stream):已創建的鏈接上的雙向字節流。

在HTTP/2中,數據流以消息的形式發送,而消息由一個或多個幀組成,幀能夠在數據流上亂序發送,而後再根據每一個幀首部的流標識符從新組裝。二進制分幀是HTTP/2的基石,其餘優化都是在這一基礎上來實現的。緩存

多路複用(Request and Response Multiplexing)

HTTP1.x中,若是想併發多個請求,必須使用多個TCP連接,且瀏覽器爲了控制資源,還會對單個域名有6-8的個數限制,以下圖,紅色圈出來的請求就因域名連接數已超過限制,而被掛起等待了一段時間:
Alt text
針對這一問題,咱們作了不少優化,例如合併請求、圖片精靈、散列域名等性能優化

在 HTTP/2 中,有了二進制分幀以後,HTTP 2.0再也不依賴TCP連接去實現多流並行了,在HTTP/2:服務器

  • 同域名下全部通訊都在單個鏈接上完成。
  • 單個鏈接能夠承載任意數量的雙向數據流。
  • 數據流以消息的形式發送,而消息又由一個或多個幀組成,多個幀之間能夠亂序發送,由於根據幀首部的流標識能夠從新組裝。

這一特性,性能會有極大的提高,由於:cookie

  • 同個域名只須要佔用一個TCP鏈接,消除了因多個TCP鏈接而帶來的延時和內存消耗。
  • 單個鏈接上能夠並行交錯的請求和響應,之間互不干擾。

流優先級( Stream priority)

在HTTP/2中,每一個請求均可以帶一個31bit的優先值,0表示最高優先級, 數值越大優先級越低。有了這個優先值,客戶端和服務器就能夠在處理不一樣的流時採起不一樣的策略,以最優的方式發送流、消息和幀。併發

服務器推送(Server push)

Server push是HTTP/2中一個很強大的功能:

  • 服務器除了響應客戶端的請求外,還能夠向客戶端額外推送資源。
  • 服務器推送的資源有本身獨立的URL, 能夠被瀏覽器緩存,能夠達到多頁面共享。
  • 資源推送遵照同源策略,服務器不可隨便推送第三方資源給客戶端。
  • 客戶端能夠拒絕推送過來的資源。

有了這一特性,咱們能夠作什麼?

  • 應用能夠經過額外的http頭部,列出須要服務器推送哪些資源。
  • 服務器能夠解析請求的html,推測出客戶端接下來須要請求的資源,而後提早向客戶端推送。
  • 等等

頭部壓縮(Header Compression)

HTTP每一次通訊都會攜帶一組頭部,用於描述此次通訊的的資源、瀏覽器屬性、cookie等,例如
Alt text

在HTTP 1.x中,這些信息都是以純文本協議發送的,給每一個請求增長了不小的負荷。

爲了減小這塊的開銷並提高性能, HTTP/2會壓縮這些首部:

  • HTTP/2在客戶端和服務器端使用「首部表」來跟蹤和存儲以前發送的鍵-值對,對於相同的數據,再也不經過每次請求和響應發送;
  • 首部表在HTTP/2的鏈接存續期內始終存在,由客戶端和服務器共同漸進地更新;
  • 每一個新的首部鍵-值對要麼被追加到當前表的末尾,要麼替換表中以前的值。

例如:下圖中的兩個請求, 請求一發送了全部的頭部字段,第二個請求則只須要發送差別數據,這樣能夠減小冗餘數據,下降開銷。

Alt text

咱們來看一個實際的例子,下面是用WireShark抓取的訪問google首頁的包:
Alt text

上圖是是訪問https://www.google.com/抓到的第一個請求的頭部,能夠看到頭部的內容,總共佔用了437 bytes,咱們選中頭部的cookie,能夠看到cookie總共佔用了118 bytes。接下來咱們看看第二個請求的頭部:

Alt text
從上圖能夠看到,得益於頭部壓縮,第二個請求中cookie只佔用了1個字節,咱們來看看變化了的Accept字段:
Alt text
因爲Accept字段與請求一中的內容不一樣,須要發送給服務器,因此佔用了29 bytes。

應用層協商協議(APLN:Aplication Layer Protocol Negotiation)

客戶端、服務器都須要升級才能支持HTTP 2.0,升級過程當中就存在HTTP1.一、HTTP 2.0並存的狀況,然而他們都使用的80端口,那麼如何來選擇使用什麼協議通訊呢?

APLN就是爲了解決這個問題的,經過協商來選擇通訊的協議:

  1. 客戶端發起請求,若是支持HTTP/2,則帶upgrade頭部:
    GET /page HTTP/1.1
    Host: server.example.com
    Connection: Upgrade, HTTP2-Settings
    Upgrade: HTTP/2.0
    HTTP2-Settings: (SETTINGS payload)
  2. 服務器不支持,則拒絕升級,經過HTTP1.1返回響應
    HTTP/1.1 200 OK
    Content-length: 243
    Content-type: text/html
    (... HTTP 1.1 response ...)
  3. 服務器支持,則接受升級,切換到新分幀,使用HTTP/2通訊。
    HTTP/1.1 101 Switching Protocols
    Connection: Upgrade
    Upgrade: HTTP/2.0
    (... HTTP 2.0 response ...)

使用協議協商,不管是哪種狀況,都不須要額外的往返,若是客戶端經過記錄或者其餘方式,知道服務器支持HTTP/2,則直接使用HTTP/2通訊,無需再協議協商。

Ending

最後,簡而概之,HTTP/2的經過支持請求與響應的多路複用來減小延遲,經過壓縮HTTP首部字段將協議開銷降至最低,同時增長對請求優先級和服務器端推送的支持。

HTTP/2性能獲得了極大的提高,咱們在HTTP 1.1時代作的有些優化反而成了雞肋,在升級過程當中,如何讓HTTP/2 和 HTTP 1.1的用戶都能獲得最優的性能,這是對於咱們的另一大挑戰。

參考資料:

  1. 《High Performance Browser Networking》 –Ilya Grigorik;
  2. 《Web性能權威指南》-李鬆峯翻譯;
  3. Jerry Qu blog 中的HTTP/2專題;
  4. HTTP/2 rfc 7540;
  5. HTTP/2 協議 中英對照版 –百度 FEX
  6. 維基百科:HTTP/2
相關文章
相關標籤/搜索