HTTP3 RFC 9114 發(fā)布,深入剖析HTTP3協(xié)議
經過了多年的努力,在 6 月 6 號,IETF (互聯網工程任務小組) 正式發(fā)布了 HTTP/3 的 RFC, 這是超文本傳輸協(xié)議(HTTP)的第三個主要版本,完整的 RFC 超過了 20000 字,非常詳細的解釋了 HTTP/3。


HTTP 歷史

1991 HTTP/1.1 2009 Google 設計了基于TCP的SPDY 2013 QUIC 2015 HTTP/2 2018 HTTP/3
HTTP2協(xié)議雖然大幅提升了HTTP/1.1的性能,然而,基于TCP實現的HTTP2遺留下3個問題:
有序字節(jié)流引出的隊頭阻塞(Head-of-line blocking),使得HTTP2的多路復用能力大打折扣;
TCP與TLS疊加了握手時延,建鏈時長還有1倍的下降空間;
基于TCP四元組確定一個連接,這種誕生于有線網絡的設計,并不適合移動狀態(tài)下的無線網絡,這意味著IP地址的頻繁變動會導致TCP連接、TLS會話反復握手,成本高昂。
HTTP3協(xié)議解決了這些問題:
HTTP3基于UDP協(xié)議重新定義了連接,在QUIC層實現了無序、并發(fā)字節(jié)流的傳輸,解決了隊頭阻塞問題(包括基于QPACK解決了動態(tài)表的隊頭阻塞);
HTTP3重新定義了TLS協(xié)議加密QUIC頭部的方式,既提高了網絡攻擊成本,又降低了建立連接的速度(僅需1個RTT就可以同時完成建鏈與密鑰協(xié)商);
HTTP3 將Packet、QUIC Frame、HTTP3 Frame分離,實現了連接遷移功能,降低了5G環(huán)境下高速移動設備的連接維護成本。

QUIC 協(xié)議概覽


HTTP over QUIC即HTTP/3的含義HTTP/3, QUIC是繞不過去的, 下面是幾個重要的QUIC特性.0 RTT建立連接
RTT: round-trip time, 僅包括請求訪問來回的時間

HTTP/2的連接建立需要3 RTT, 如果考慮會話復用, 即把第一次握手計算出來的對稱密鑰緩存起來, 那也需要2 RTT. 更進一步的, 如果TLS升級到1.3, 那么HTTP/2連接需要2RTT, 考慮會話復用需要1RTT. 如果HTTP/2不急于HTTPS, 則可以簡化, 但實際上幾乎所有瀏覽器的設計都要求HTTP/2需要基于HTTPS.HTTP/3首次連接只需要1RTT, 后面的鏈接只需要0RTT, 意味著客戶端發(fā)送給服務端的第一個包就帶有請求數據, 其主要連接過程如下:首次連接, 客戶端發(fā)送 Inchoate Client Hello, 用于請求連接;服務端生成g, p, a, 根據g, p, a算出A, 然后將g, p, A放到Server Config中在發(fā)送 Rejection消息給客戶端.客戶端接收到g,p,A后, 自己再生成b, 根據g,p,a算出B, 根據A,p,b算出初始密鑰K, B和K算好后, 客戶端會用K加密HTTP數據, 連同B一起發(fā)送給服務端. 服務端接收到B后, 根據a,p,B生成與客戶端同樣的密鑰, 再用這密鑰解密收到的HTTP數據. 為了進一步的安全(前向安全性), 服務端會更新自己的隨機數a和公鑰, 在生成新的密鑰S, 然后把公鑰通過 Server Hello發(fā)送給客戶端. 連同Server Hello消息, 還有HTTP返回數據.

連接遷移
Connection ID, 即使IP或者端口發(fā)生變化, 只要Connection ID沒有變化, 那么連接依然可以維持.隊頭阻塞/多路復用
HTTP/1.1和HTTP/2都存在隊頭阻塞的問題(Head Of Line blocking).ACK消息, 以確認對象已接受數據. 如果每次請求都要在收到上次請求的ACK消息后再請求, 那么效率無疑很低. 后來HTTP/1.1提出了Pipeline技術, 允許一個TCP連接同時發(fā)送多個請求. 這樣就提升了傳輸效率.
Frame通過一條TCP連接同時被傳輸, 這樣即使一個請求被阻塞, 也不會影響其他的請求.
但是, HTTP/2雖然可以解決請求這一粒度下的阻塞, 但HTTP/2的基礎TCP協(xié)議本身卻也存在隊頭阻塞的問題. HTTP/2的每個請求都會被拆分成多個Frame, 不同請求的Frame組合成Stream, Stream是TCP上的邏輯傳輸單元, 這樣HTTP/2就達到了一條連接同時發(fā)送多個請求的目標, 其中Stram1已經正確送達, Stram2中的第三個Frame丟失, TCP處理數據是有嚴格的前后順序, 先發(fā)送的Frame要先被處理, 這樣就會要求發(fā)送方重新發(fā)送第三個Frame, Steam3和Steam4雖然已到達但卻不能被處理, 那么這時整條鏈路都會被阻塞.


QUIC的傳輸單位是Packet, 加密單元也是Packet, 整個加密, 傳輸, 解密都基于Packet, 這就能避免TLS的阻塞問題. QUIC基于UDP, UDP的數據包在接收端沒有處理順序, 即使中間丟失一個包, 也不會阻塞整條連接. 其他的資源會被正常處理.
擁塞控制
慢啟動: 發(fā)送方像接收方發(fā)送一個單位的數據, 收到確認后發(fā)送2個單位, 然后是4個, 8個依次指數增長, 這個過程中不斷試探網絡的擁塞程度. 避免擁塞: 指數增長到某個限制之后, 指數增長變?yōu)榫€性增長 快速重傳: 發(fā)送方每一次發(fā)送都會設置一個超時計時器, 超時后認為丟失, 需要重發(fā) 快速恢復: 在上面快速重傳的基礎上, 發(fā)送方重新發(fā)送數據時, 也會啟動一個超時定時器, 如果收到確認消息則進入擁塞避免階段, 如果仍然超時, 則回到慢啟動階段.
1. 熱插拔
2. 前向糾錯 FEC

3. 單調遞增的Packer Number
Sequence Number和ACK來確認消息是否有序到達, 但這樣的設計存在缺陷.RTT: Round Trip Time, 往返事件 RTO: Retransmission Timeout, 超時重傳時間

Sequence Number不同, Packet Number嚴格單調遞增, 如果Packet N丟失了, 那么重傳時Packet的標識就不會是N, 而是比N大的數字, 比如N+M, 這樣發(fā)送方接收到確認消息時, 就能方便的知道ACK對應的原始請求還是重傳請求.4. ACK Delay

5. 更多的ACK塊
ACK, 而QUIC最多可以捎帶256個ACK block, 在丟包率比較嚴重的網絡下, 更多的ACK可以減少重傳量, 提升網絡效率.瀏覽控制
Stream, 好比有一條道路, 量都分別有一個倉庫, 道路中有很多車輛運送物資. QUIC的流量控制有兩個級別: 連接級別(Connection Level)和Stream 級別(Stream Level).
(flow control receivce offset - consumed bytes) < (max receive window/2)時, 接收方會發(fā)送WINDOW_UPDATE frame告訴發(fā)送方你可以再多發(fā)送數據, 這時候flow control receive offset就會偏移, 接收窗口增大, 發(fā)送方可以發(fā)送更多數據到接收方.
Stream級別對防止接收端接收過多數據作用有限, 更需要借助Connection級別的流量控制. 理解了Stream流量那么也很好理解Connection的流控. Stream中,
接收窗口=最大接受窗口 - 已接收數據而對于Connection來說:接收窗口 = Stream1 接收窗口 + Stream2 接收窗口 + ... + StreamN 接收窗口參考鏈接
推薦閱讀:
不是你需要中臺,而是一名合格的架構師(附各大廠中臺建設PPT)
