QUIC的前世今生——HTTP演变史
1.HTTP演變史
在我們更深入地研究 HTTP/3之前,讓我們快速了解一下 HTTP 多年來的演變,以便更好地理解為什么需要HTTP/3:
 
 1.1 HTTP 0.9:只有一行的協議
 Tim Berners-Lee 最初的HTTP 建議是以簡潔為出發點設計的,目的是推動他的另一個剛剛萌芽的思想——萬維網的應用。1991年,是一個單純的年代,網上只有文字,看不了圖。
請求只有一行,包括GET 方法和要請求的文檔的路徑。響應是一個超文本文檔,沒有首部,也沒有其他元數據,只有HTML。HTTP 0.9 的功能:
◎客戶端 / 服務器、請求 / 響應協議;
◎ASCII 協議,運行于 TCP/IP 鏈接之上;
◎設計用來傳輸超文本文檔(HTML);
◎服務器與客戶端之間的連接在每次請求之后都會關閉。
1.2 HTTP 1.0:迅速發展及參考性RFC
 1991 年到1995 年,HTML 規范和一種新型的名叫“Web 瀏覽器”的軟件都獲得了快速發展。于是,1996 年,HTTP 工作組發布了RFC 1945,在該文檔中記錄了許多HTTP/1.0實現的通用方法,于是HTTP/1.0就誕生了。HTTP 1.0 的請求對我們而言應該是非常熟悉的:
請求行中包含HTTP 版本號,隨后是請求首部;響應狀態,后跟響應首部。該協議的關鍵變化:
◎請求可以由于多行首部字段構成;
◎響應對象前面添加了一個響應狀態行;
◎響應對象也有自己的由換行符分隔的首部 字段;
◎響應對象不局限于超文本;
◎服務器與客戶端之間的連接在每次請求之后都會關閉。
1.3 HTTP 1.1:互聯網標準
 在1997年1月,發布了HTTP/1.1的第一個正式標準 RFC2068[2]。然后,在兩年半之后的1999年6月,許多改進和更新被納入該標準,并以 RFC 2616[3]的形式發布。
◎新增了POTIONS、PUT、DELETE、TRACE、CONNECT等新方法;
◎強化了緩存管理和控制;
◎支持維持持久連接,支持通知服務器棄用連接;也就是說TCP連接默認不關閉,可以被多個請求復用,不用聲明Connection: keep-alive;
◎請求HTML文件的時候要求攜帶編碼、字符集、cookie元數據等信息;
◎支持原始HTML請求的分塊響應,利于傳輸大文件;
HTTP 1.1 改變了HTTP 協議的語義,默認使用持久連接。換句話說,除非明確告知(通過Connection: close 首部),否則服務器默認會保持連接打開。不過,這個功能也反向移植到了HTTP 1.0,可以通過Connection: Keep-Alive 首部來啟用。實際上,如果你使用的是HTTP 1.1,從技術上說不需要Connection: Keep-Alive 首部,但很多客戶端還是選擇加上它。
1.4 HTTP 1.X的缺陷
- 連接無法復用
 連接無法復用會導致每次請求都經歷三次握手和慢啟動。三次握手在高延遲的場景下影響較明顯,慢啟動則對大量小文件請求影響較大(沒有達到最大窗口請求就被終止)。
 ◎HTTP/1.0 傳輸數據時,每次都需要重新建立連接,增加延遲。
 ◎HTTP/1.1 加入 keep-alive 可以復用一部分連接,當頁面上有大量元素時,這樣的等待會造成頁面內容的順序加載,為了提高吞吐量,現在瀏覽器會對每個域名至多打開6個連接,并且重用它們。然而這樣的提速仍不滿足當前的性能要求,為此還有切分域名域(Sharding Dominant Domains)等優化方法。
- Head-Of-Line Blocking(HOLB)
 導致帶寬無法被充分利用。HOLB是指一系列包(package)因為第一個包被阻塞;當頁面中需要請求很多資源的時候,HOLB(隊頭阻塞)會導致在達到最大請求數量時,剩余的資源需要等待其他資源請求完成后才能發起請求。
 ◎HTTP 1.0:下個請求必須在前一個請求返回后才能發出,request-response對按序發生。顯然,如果某個請求長時間沒有返回,那么接下來的請求就全部阻塞了。
 ◎HTTP 1.1:嘗試使用 pipeling 來解決,即瀏覽器可以一次性發出多個請求(同個域名,同一條 TCP 鏈接)。但 pipeling 要求返回是按序的,那么前一個請求如果很耗時(比如處理大圖片),那么后面的請求即使服務器已經處理完,仍會等待前面的請求處理完才開始按序返回。所以,pipeling 只部分解決了 HOLB。
 
 1.5 HTTP 2.0:改進傳輸性能
 隨著我們越來越多地把應用(社交媒體、電子郵件、新聞和視頻,以及個人的生活與工作內容)部署到Web 上,HTTP 的問題也出現了。今天,用戶和Web 開發者都迫切想要通過HTTP 1.1 達到一種幾近實時的響應速度和協議性能,而要滿足這個需求,僅靠在原協議基礎上修修補補是不夠的。
2015 年,HTTP/2 發布。HTTP/2 是現行 HTTP 協議(HTTP/1.x)的替代,但它不是重寫,HTTP 方法/狀態碼/語義都與 HTTP/1.x 一樣。HTTP/2 基于 SPDY3,專注于性能,最大的一個目標是在用戶和網站間只用一個連接(connection),主要有如下功能:
◎使用虛擬的流傳輸消息,解決了HTTP一個連接中應用層的隊頭阻塞的問題;
◎使用了二進制協議,不再是純文本,避免文本歧義,縮小了請求體積;
◎實現了多路復用,提高了連接的利用率,在擁塞控制方面有了更好的能力提升;
◎使用HPACK首部壓縮方案壓縮頭部信息,大大節約了帶寬;
◎增強了安全性,使用HTTP/2,要求必須至少用TLS1.2;
◎允許服務器主動向客戶端推送數據;
 
 在 HTTP/2 中引入了多路復用的技術。多路復用很好的解決了瀏覽器限制同一個域名下的請求數量的問題,同時也接更容易實現全速傳輸,畢竟新開一個 TCP 連接都需要慢慢提升傳輸速度。大家可以直觀感受下 HTTP/2 比 HTTP/1 到底快了多少。有關HTTP/2的原理實現資料可見文末的參考資料。
 
 目前騰訊云CDN也已支持HTTP2,只需在官網控制臺對加速域名進行配置,即可完成對資源的http2支持,不需要源站支持http2。
 
2.HTTP3
雖然 HTTP/2 解決了很多之前舊版本的問題,但是它還是存在一個巨大的問題,主要是底層支撐的 TCP 協議造成的。上文提到 HTTP/2 使用了多路復用,一般來說同一域名下只需要使用一個 TCP 連接。但當這個連接中出現了丟包的情況,那就會導致 HTTP/2 的表現情況反倒不如 HTTP/1 了。因為在出現丟包的情況下,整個 TCP 都要開始等待重傳,也就導致了后面的所有數據都被阻塞了。但是對于 HTTP/1.1 來說,可以開啟多個 TCP 連接,出現這種情況反到只會影響其中一個連接,剩余的 TCP 連接還可以正常傳輸數據。
那么可能就會有人考慮到去修改 TCP 協議,其實這已經是一件不可能完成的任務了。因為 TCP 存在的時間實在太長,已經充斥在各種設備中,并且這個協議是由操作系統實現的,更新起來不大現實?;谶@個原因,Google 就更起爐灶搞了一個基于 UDP 協議的 QUIC 協議,并且使用在了 HTTP/3 上,HTTP/3 之前名為 HTTP-over-QUIC,從這個名字中我們也可以發現,HTTP/3 最大的改造就是使用了 QUIC。
由于HTTP/3還處于草案階段,這里只對HTTP/3功能更做一個整體的介紹,下面是整體的架構圖:
 
上面我們談到到了 head-of-line blocking 的問題,這也是 HTTP3 最大改變的地方。它不使用 TCP 作為會話的傳輸層,而是使用 QUIC,一種新的互聯網傳輸協議,除其他外,它在傳輸層引入了流作為最優先的傳輸。QUIC 流共享相同的 QUIC 連接,所以創建新的 QUIC 流不需要額外的握手和緩慢的啟動,但是 QUIC 流是獨立交付的,因此在大多數情況下,影響一個流的數據包丟失不會影響其他流,因為 QUIC 數據包封裝在 UDP 數據包之上。
與 TCP 相比,使用 UDP 提供了更多的靈活性,并且使 QUIC 實現安裝在用戶空間(user-space)中ーー對協議實現的更新不像 TCP 那樣與操作系統更新綁定在一起。使用 QUIC,HTTP 級別的流可以簡單地映射到 QUIC 流之上,從而獲得 HTTP/2的所有好處,而不會出現“head-of-line blocking”。
QUIC 還將典型的 3-way TCP 握手與 TLS 1.3 的握手相結合。組合這些步驟意味著默認情況下提供了加密和身份驗證,并且還支持更快的連接建立。換句話說,即使 HTTP 會話中的初始請求需要一個新的 QUIC 連接,在數據開始流動之前產生的延遲也低于使用 TLS 的 TCP。
 ◎底層采用了UDP,通過在用戶空間的QUIC協議保證了傳輸的可靠性;
◎引入了Connection ID,不再需要向TCP那樣基于IP和端口進行綁定連接,支持連接遷移,也就是說,從移動網絡,切換到WIFI,可以繼續使用同一個連接;
◎頭部壓縮算法由HPACK替換為了QPACK,以便能夠支持亂序發送,優化壓縮率;
◎QUIC包含了一個內嵌的TLS1.3,因此支持1-RTT快速建立連接;
3.CDN中QUIC實踐
騰訊云CDN當前已支持HTTP3,您可在官網產品文檔中找到QUIC內測申請鏈接,通過內測審核后,只需要將域名接入到官網控制臺,開啟QUIC功能,即可完成對資源的HTTP3支持,不需要源站做任何改動,當前支持的QUIC版本有H3-Q050,Q046,Q043。訪問流程如下所示:
 
 3.1 協議協商
 一般情況下,Chrome瀏覽器和服務器端協商使用QUIC協議要經過如下步驟:
客戶端發出tcp請求
服務端如果支持quic可以通過響應頭alt-svc告知客戶端
客戶端同時發起tcp連接和quic連接競賽
一旦quic建立連接獲勝則采用quic協議發送請求
如遇網絡或服務器不支持quic/udp,客戶端標記quic為broken
傳輸中的請求通過tcp重發
alt-svc 主要包含以下信息:
◎quic:監聽的端口;
◎ma:有效時間,單位是秒,承諾在這段時間內都支持 QUIC;
◎版本號:QUIC 的迭代很快,這里列出所有支持的版本號。
在完成域名接入后,使用Chrome訪問需要啟動QUIC,chrome版本88.0.4324.182(正式版本)默認支持的QUIC協議是Q050:
 
 
 wireshark抓包分析:
 
[1] Web性能權威指南
 [2] 一文讀懂 HTTP/2 及 HTTP/3 特性
 [3] HTTP/3 原理與實踐
 [4] HTTP探索之路 - HTTP1/HTTP2/QUIC
 [5] HTTP/3:讓傳輸效率再一次起飛 | QUIC
 [6] HTTP3 協議
關注騰訊云CDN公眾號,技術干貨一手掌握!
 
總結
以上是生活随笔為你收集整理的QUIC的前世今生——HTTP演变史的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 应用于CDN的GSLB系统
- 下一篇: 执着
