從 HTTP/1.1 到 HTTP/3,解決了一些舊協議的問題,引入了好用的新功能。
HTTP/1.1
HTTP/1.1 通過在傳輸層和應用層之間增加 SSL/TSL 解決數據不安全的問題,但它本身還有一些其它的不足。
- 同一時間,一個連接只能對應一個請求,針對同一個域名,大多數瀏覽器允許同時最多6個併發請求
- 只允許客户端主動發起請求,一個請求只能對應一個響應
- 同一個會話的多次請求中,頭信息會被重複傳輸
針對於以上情況,增加了新的協議 SPDY。
SPDY
SPDY(speedy的縮寫),是基於 TCP 的應用層協議,它強制要求使用 SSL/TLS,SPDY 並不用於取代 HTTP,它只是修改了 HTTP 請求與響應的傳輸方式,只需增加一個 SPDY 層,現有的所有服務端應用均不用做任何修改,SPDY 是 HTTP/2 的前身。
HTTP/2
HTTP/2(類似於HTTP+SPDY,不強制使用SSL,但大部分都會使用SSL)在底層傳輸做了很多的改進和優化,但在語意上完全與HTTP/1.1兼容,比如請求方法(如 GET、POST)、Status Code、各種Headers等都沒有改變。
超快的加載速度
在 HTTP/2測速網站中,可以看到 HTTP/2 和 HTTP/1.1 對比170張32*48像素的小圖組合成的大圖加載速度的時長對比。那為什麼會存在如此大的差異呢,在於HTTP/2在很多方面做了調整。
二進制格式
首先就是 HTTP/2 採用二進制格式傳輸數據,而非 HTTP/1.1 的文本格式。
多路複用
新的二進制分幀機制改變了客户端與服務器之間交互數據的方式,這裏有幾個新的概念。
• 流:已建立的連接上的雙向字節流。
• 消息:與邏輯消息對應的完整的一系列數據幀。
• 幀:HTTP 2.0 通信的最小單位,每個幀包含幀首部,至少也會標識出當前幀所屬的流
每個數據流以消息的形式發送,而消息由一或多個幀組成,這些幀可以亂序發送,然後再根據每個幀首部的流標識符重新組裝。
圖中包含了同一個連接上多個傳輸中的數據流:客户端正在向服務器傳輸一個 DATA 幀(stream 5),與此同時,服務器正向客户端亂序發送 stream 1 和 stream 3 的一系列幀。此時,一個連接上有 3 個請求 / 響應並行交換。
把 HTTP 消息分解為獨立的幀,交錯發送,然後在另一端重新組裝是 HTTP 2.0 重要的一項增強。事實上,這個機制會在整個 Web 技術棧中引發一系列連鎖反應, 從而帶來巨大的性能提升。
• 並行交錯地發送請求,請求之間互不影響
• 並行交錯地發送響應,響應之間互不干擾
• 只使用一個連接即可並行發送多個請求和響應
• 消除不必要的延遲,從而減少頁面加載的時間
• 不必再為繞過 HTTP 1.x 連接限制而多做很多工作(如image sprites、合併CSS\JS、內嵌CSS\JS\Base64圖片、域名分片)
首部壓縮
HTTP 的每一次通信都會攜帶一組首部,用於描述傳輸的資源及其屬性。在 HTTP 1.x 中,這些元數據都是以純文本形式發送的,通常會給每個請求增加 500~800 字 節的負荷。如果算上 HTTP cookie,增加的負荷通常會達到上千字節。為減少這些開銷並提升性能,HTTP 2.0 會壓縮首部元數據。
客户端和服務器緩存上一次的請求,只發不同的請求頭,靜態表儲存着常用請求頭,動態表是隨着新的請求增加新的請求頭,客户端和服務器同步保存兩張表,一個頭信息對應着一個索引,如果請求頭存在於索引表中,只需發索引號。
服務器推送
HTTP1 中只允許客户端主動發起請求,一個請求只能對應一個響應,HTTP 2.0 新增的一個新功能,就是服務器可以對一個客户端請求發送多個響應。除了對最初請求的響應外,服務器還可以額外向客户端推送資源,而無需客户端明確地請求。
Web應用可能存在幾十個資源,如果服務器能主動的推送資源給服務器,客户端就不需要分析服務器提供的文檔再逐個查找,能減少額外的時間延遲。服務器推送功能在網頁中嵌入的CSS、JavaScript 或者嵌入其它資源有應用到。
並且還帶來了這些好處
- 客户端可以緩存推送過來的資源
- 客户端可以拒絕推送過來的資源
- 推送資源可以由不同的頁面共享
- 服務器可以按照優先級推送資源
以上都是 HTTP/2 提供的新特性,以解決 HTTP1 的不足,但它自身也存在一些問題。
隊頭阻塞
請求中如果丟失了一個包,導致後面的請求阻塞,此時會等待丟失的包重發,這是TCP底層決定的。
握手延遲
HTTP2的傳輸層協議還是使用的TCP,仍然有握手的環節。
RTT(Round Trip Time):往返時延,可以簡單理解為通信一來一回的時間,建立連接 一個RTT約100ms 還加上TLS 握手要300ms,仍然需要不少時間。
HTTP/3
為了解決以上問題,於是就有了 HTTP/3,HTTP/3 由 Google 開發,棄用 TCP協議,改為使用基於 UDP 協議的 QUIC 協議實現。
解決隊頭阻塞
QUIC協議使用的 UDP 協議,直接扔無序的數據過來就行,無需排隊等待請求的響應,就不存在隊頭阻塞的問題。
解決握手延遲
而 UDP 連接無需 "握手",也就沒有 "握手延遲" 的問題。
存疑
1、UDP 無需建立連接,如何來保證 "可靠傳輸" 呢?
UDP 接收數據包,如果丟失也不會重新傳遞,直接對接應用層 HTTP 協議的話,數據可能不完整,這裏在應用層和傳輸層中還增加了 QUIC 協議,如果丟失了包,會告知對方的 QUIC 層,重新傳輸丟失的包。也就是説由QUIC來保證"可靠傳輸",相當於實現了TCP的功能。
2、為何Google不開發一個新的不同於TCP、UDP的傳輸層協議?
目前世界上的網絡設備基本只認TCP、UDP,如果要修改傳輸層,意味着操作系統的內核也要修改,另外,許多TCP新特性都因缺乏廣泛支持而沒有得到廣泛的部署或使用,因此,要想開發並應用一個新的傳輸層協議,是極其困難的一件事情。
連接遷移
TCP 基於4要素(源IP、源端口、目標IP、目標端口),切換網絡時至少會有一個要素髮生變化,導致連接發生變化,當連接發生變化時,如果還使用原來的TCP連接,則會導致連接失敗,就得等原來的連接超時後重新建立連接。
所以我們有時候發現切換到一個新網絡時,即使新網絡狀況良好,但內容還是需要加載很久(可能會出現網絡異常的情況)。
QUIC的連接不受4要素的影響,當4要素髮生變化時,原連接依然維持,QUIC連接不以4要素作為標識,而是使用一組Connection ID(連接ID)來標識一個連接,即使IP或者端口發生變化,只要Connection ID沒有變化,那麼連接依然可以維持,當設備連接到Wi-Fi時,將進行中的下載從蜂窩網絡連接轉移到更快速的Wi-Fi連接,當Wi-Fi連接不再可用時,將連接轉移到蜂窩網絡連接。
總結
- HTTP/1 存在請求數量受限、服務器無法主動推送消息、頭部信息過多的問題
- HTTP/2 增加二進制數據、多路複用、首部壓縮、服務器推送的功能,存在隊頭阻塞、握手延遲的問題
- HTTP/3 使用基於 UDP 協議的 QUIC 協議實現,解決隊頭阻塞、握手延遲的問題,增加連接遷移的特性
以上就是HTTP/2,HTTP/3的相關介紹。更多有關 前端、網絡協議 的內容可以參考我其它的博文,持續更新中~
參考文獻:
《Web性能權威指南》
參考視頻:《網絡協議從入門到底層原理》