HTTP/2 h2 協議簡介


隨着web技術的飛速發展,1999年制定的HTTP 1.1已經無法滿足大家對性能的要求,Google推出協議SPDY,旨在解決HTTP 1.1中廣為人知的性能問題。SPDY得到了Chrome、Firefox和Opera的支持,很多大型網站(如谷歌、Twitter、Facebook、淘寶)都對兼容客戶端使用SPDY。SPDY在被行業采用並證明能夠大幅提升性能之后,已經具備了成為一個標准的條件。

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

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

二進制分幀(Binary Framing)

HTTP1.x以換行符作為純文本的分隔符。

HTTP/2將所有傳輸的信息分割為更小的消息和幀,並對它們采用二進制格式的編碼,我們先了解幾個概念:

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

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

多路復用(Request and Response Multiplexing)

HTTP1.x中,如果想並發多個請求,必須使用多個TCP鏈接,且瀏覽器為了控制資源,還會對單個域名有6-8的個數限制,如下圖,紅色圈出來的請求就因域名鏈接數已超過限制,而被掛起等待了一段時間:
img
針對這一問題,我們做了很多優化,例如合並請求、圖片精靈、散列域名等

在 HTTP/2 中,有了二進制分幀之后,HTTP 2.0不再依賴TCP鏈接去實現多流並行了,在HTTP/2:

  • 同域名下所有通信都在單個連接上完成。
  • 單個連接可以承載任意數量的雙向數據流。
  • 數據流以消息的形式發送,而消息又由一個或多個幀組成,多個幀之間可以亂序發送,因為根據幀首部的流標識可以重新組裝。

這一特性,性能會有極大的提升,因為:

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

流優先級( Stream priority)

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

服務器推送(Server push)

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

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

有了這一特性,我們可以做什么?

  • 應用可以通過額外的http頭部,列出需要服務器推送哪些資源。
  • 服務器可以解析請求的html,推測出客戶端接下來需要請求的資源,然后提前向客戶端推送。
  • 等等

頭部壓縮(Header Compression)

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

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

為了減少這塊的開銷並提升性能, HTTP/2會壓縮這些首部:

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

例如:下圖中的兩個請求, 請求一發送了所有的頭部字段,第二個請求則只需要發送差異數據,這樣可以減少冗余數據,降低開銷。

img

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

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

img
從上圖可以看到,得益於頭部壓縮,第二個請求中cookie只占用了1個字節,我們來看看變化了的Accept字段:
img
由於Accept字段與請求一中的內容不同,需要發送給服務器,所以占用了29 bytes。

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

客戶端、服務器都需要升級才能支持HTTP 2.0,升級過程中就存在HTTP1.1、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的用戶都能得到最優的性能,這是對於我們的另外一大挑戰。

轉自:
https://blog.csdn.net/whatday/article/details/101927361


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM