目錄
因爲HTTP/1.1性能以及速度方面的問題,人們想了一系列的優化措施。當優化措施依然不能滿足要求時,就需要對協議進行升級。於是,有了HTTP/2。
源起
HTTP/2基於SPDY。SPDY 音同SPEEDY,也就是快,如果你看過手把手帶你體驗 HTTP/3 或者 【技術】QUIC的那些事 | QUIC爲什麼那麼快,那麼也就知道這個套路了。
2009 年,Google 的工程師Mike Belshe 和Roberto Peon 提出了一種HTTP 的替代方案:SPDY。
SPDY 不是第一個希望替代HTTP 的方案,但它是其中最重要的一個,因爲它帶來了顯而易見的性能提升。
SPDY爲HTTP/2 奠定了基礎,並證明了其中一些關鍵特性的合理性,如多路複用、幀和首部壓縮等。SPDY很快被整合進了Chrome 和Firefox,並最終幾乎被所有主流瀏覽器所採有。而且幾乎在同一時間,服務器和網絡代理也對SPDY 提供了必要的支持。
2012 年初,HTTP 工作組啓動了開發下一個HTTP 版本的工作,其綱領的關鍵部分闡述了工作組對新協議的一些期望,HTTP/2 的主要目標是改進傳輸性能,實現低延遲和高吞吐量。
HTTP/2 被寄予瞭如下期望:
-
相比於使用TCP 的HTTP/1.1,最終用戶可感知的多數延遲都有能夠量化的顯著改善;
-
解決HTTP 中的隊頭阻塞問題;
-
並行的實現機制不依賴與服務器建立多個連接,從而提升TCP 連接的利用率,特別是在擁塞控制方面;
-
保留HTTP/1.1 的語義,可以利用已有的文檔資源(如上所述),包括(但不限於)HTTP 方法、狀態碼、URI 和首部字段;
-
明確定義HTTP/2 和HTTP/1.x 交互的方法,特別是通過中介時的方法(雙向);明確指出它們可以被合理使用的新的擴展點和策略。
工作組發出了徵求建議書的通知,並最終決定使用SPDY 作爲HTTP/2 的起點。RFC 7540 在2015 年5 月14 日發佈了,HTTP/2 成爲正式協議。
HTTP/2瀏覽器支持情況:
備註:HTTP/2也寫作HTTP2、H2
協議格式
分幀層
HTTP /2 性能增強的核心,全在於新增的二進制分幀層,它定義瞭如何封裝HTTP 消息並在客戶端與服務器之間傳輸。
HTTP2二進制分幀層
這裏所謂的“層”,指的是位於套接字接口與應用可見的高層HTTP API 之間的一個新機制。HTTP 的語義,包括各種動詞、方法、首部,都不受影響,不同的是傳輸期間對它們的編碼方式變了。HTTP/1 以換行符作爲純文本的分隔符,而HTTP2 將所有傳輸的信息分割爲更小的消息和幀,並對它們採用二進制格式的編碼(HTTP爲ASCII)。
所有HTTP/2 通信都在一個連接上完成,這個連接可以承載任意數量的雙向數據流。相應地,每個數據流以消息的形式發送,而消息由一或多個幀組成,這些幀可以亂序發送,然後再根據每個幀首部的流標識符重新組裝。
要理解HTTP/2,就必須理解流、消息和幀這幾個基本概念。
-
所有通信都在一個 TCP 連接上完成(HTTP1,對單個域名,可能打開4~6個TCP連接)。
-
流是連接中的一個虛擬信道,可以承載雙向的消息;每個流都有一個唯一的整數標識符(1、2…N)。
-
消息是指邏輯上的 HTTP 消息,比如請求、響應等,由一或多個幀組成。
-
幀是最小的通信單位,承載着特定類型的數據,如 HTTP 首部、負荷,等等
幀由幀首部和負載組成,幀首部長度相同,都是9個字節:
具體字段含義如下:
幀類型
幀類型如下:
1. DATA幀
2. HEADERS幀
3. PRIORITY幀
4. RST_STREAM幀
關閉連接時使用,類似於TCP的RST。
5. SETTINGS幀
如果一端接收並處理了SETTINGS 幀,就必須返回一個SETTINGS 幀,在幀首部中帶上ACK 標識(0x1)。這是SETTINGS 幀裏定義的唯一的標識位。這樣發送端就知道接收端收到了新的SETTINGS 幀,並會遵守SETTINGS 幀的設置。
6. PUSH_PROMISE幀
7. PING幀
作用類似於 ping 。
8. GOAWAY幀
9. WINDOW_UPDATE幀
備註:WINDOW_UPDATE 幀沒有專用標識
10. CONTINUATION幀
首部壓縮
HTTP 的每一次通信都會攜帶一組首部,用於描述傳輸的資源及其屬性。在HTTP1 中,這些元數據都是以純文本形式發送的,通常會給每個請求增加500~800 字節的負荷。如果算上HTTP cookie,增加的負荷通常會達到上千字節。爲減少這些開銷並提升性能,HTTP/2 會壓縮首部元數據:
-
HTTP/2 在客戶端和服務器端使用“首部表”來跟蹤和存儲之前發送的鍵-值對
-
首部表在HTTP/2的連接存續期內始終存在,由客戶端和服務器共同漸進地更新
-
每個新的首部鍵-值對要麼被追加到當前表的末尾,要麼替換表中之前的值
交互流程
HTTP2的交互流程:
HTTP2流、消息和幀
HTTP2:多向請求和響應
HTTP/2 新增的一個強大的新功能,就是服務器可以對一個客戶端請求發送多個響應。除了對最初請求的響應外,服務器還可以額外向客戶端推送資源而無需客戶端明確地請求。
HTTP2推送
Curl 查看 HTTP/2
通過curl查看HTTP2的交互流程:curl -v --http2 https://cn.bing.com
備註:H2即爲HTTP/2
從交互可以看出cn.bing.com即支持HTTP/2,也支持HTTP/1.1,由於上層指定了HTTP/2,因此最終的交互流程是HTTP/2.
對應抓包如下:
在抓包中,我們也能看出當前走的是HTTP/2協議,任選TLSv1.2的Application Data行,並點開:
抓包顯示,也確實是HTTP/2協議。
HTTP/2默認支持HTTPS,端口爲443。
如果不指定HTTP/2,輸入命令:curl -v https://cn.bing.com,輸出如下:
對應抓包爲:
實際上,到這步,抓包中並沒有顯示到底是HTTP/2還是HTTP/1,任選TLSv1.2的Application Data行,並點開,看具體傳輸報文:
備註:
-
在測試過程中,發現cn.bing.com有測不準原理,有些時候返回支持HTTP/2和HTTP1.1、有些時候只返回HTTP1.1(通過ALPN),因此即使指定了HTTP/2,也不一定走HTTP2流程。
-
在Windows下測試時,有些時候雖然不指定HTTP/2,當cn.bing.com返回HTTP/2時,也會走HTTP/2,不確定這個是curl默認選的,還是curl緩存了之前的設置。
瀏覽器查看HTTP/2
使用Firefox瀏覽器。
首先是默認方式訪問並抓包:
抓包顯示是HTTP/2,那麼,Firefox是怎麼知道要用HTTP/2呢?
在TLSv1.2的Client Hello報文中,有如下信息:
報文顯示,客戶端向服務端發送的Client Hello報文中的ALPN部分表明了支持的協議爲HTTP/2及HTTP1.1。
那麼,看下服務端的Server Hello,信息如下:
報文顯示,服務端選擇了HTTP/2的交互方式,Application Data也確實顯示是HTTP/2方式。
由於前面我們講述了HTTP2的報文格式,抓包中Application Data報文是加密的,直接看不出來,爲了看具體HTTP2報文格式,可以通過如下方式(Chrome 瀏覽器和FireFox瀏覽器):
-
設置用戶變量:SSLKEYLOGFILE,值爲會話密鑰的存儲文件(設置用戶變量後,需要重啓瀏覽器
2. 在Wireshark中設置密鑰的路徑:Edit-Preference-Protocols-SSL:
在瀏覽器中打開bing網站,並抓包:
可以看到,此時Wireshark已經能解密出具體報文了,並且顯示出了具體的報文類型,譬如WINDOW_UPDATA報文。
進一步,過濾HTTP/2的報文:
以HEADERS報文爲例,具體看一下抓包中的信息。
長度信息:
前三字節爲報文長度,值爲0x027f,十進制爲639
類型信息:
第4字節值類型爲TYPE,值爲0x01,爲HEADERS報文
FireFox的HTTP/2是默認打開的,如果要使用HTTP1.1,得關閉這個使能:
-
瀏覽器中輸入:about:config
-
輸入:
network.http.spdy.enabled.http2,將這個配置置爲false(雙擊即可)
其他
優化
爲了加快訪問速度,HTTP/1進行了一系列的優化,但是由於HTTP/2、採取了一些設計上的優勢,因此HTTP/1的優化,有些HTTP/2拋棄了;有些依然保留,具體如下:
HTTP/2使用率
參考資料
1. 《HTTP權威指南》
2. 《HTTP/2基礎教程》
3.《Web性能權威指南》
4. https://http2-explained.haxx.se/en
https://joji.me/zh-cn/blog/walkthrough-decrypt-ssl-tls-traffic-https-and-http2-in-wireshark/