QUIC/HTTP3 协议简析
從 HTTP 的進(jìn)化歷史講起,細(xì)說(shuō)使用協(xié)議的變遷,了解原因發(fā)現(xiàn)問(wèn)題,解碼 QUIC 在 HTTP3 中的支撐作用,共同探討 HTTP3 的未來(lái)。
HTTP、HTTP2 和 HTTP3
先和大家來(lái)回顧一下 HTTP 的歷史,看看 HTTP3 相比 HTTP、HTTP2 都有哪些改進(jìn)和升級(jí)的地方。
HTTP VS HTTP2
多路復(fù)用:多路復(fù)用時(shí),多文件傳輸有時(shí)只需維護(hù)一個(gè) TCP 連接。如果是 HTTP1 協(xié)議下,每份資源的傳輸對(duì)應(yīng)一個(gè) TCP 連接,一般最多只能開(kāi)啟 6 個(gè) TCP 連接來(lái)傳輸多路數(shù)據(jù),后續(xù)每增加一個(gè)新鏈接就會(huì)因?yàn)閾矶聠?wèn)題卡死,進(jìn)而導(dǎo)致整個(gè)進(jìn)程無(wú)法運(yùn)行。因此HTTP/2解決了 HTTP 的隊(duì)頭阻塞問(wèn)題。
頭部壓縮和 Server Push:HTTP2 會(huì)通過(guò) HPACK 做頭部壓縮。同時(shí) HTTP2 是二進(jìn)制協(xié)議,在解析上相比基于文本的 HTTP解析效率上有所提升,并且 HTTP2 還增加了 Server Push。
在 TCP 下,依然無(wú)法解決延遲問(wèn)題,比如為防止初始阻塞而引入的慢啟動(dòng);TCP 隊(duì)頭阻塞,比如由于發(fā)生丟包,整個(gè)連接涉及的傳輸數(shù)據(jù)都需要重傳而引起的阻塞。
盡管 HTTP2 相比 HTTP 已經(jīng)有了改進(jìn)的地方,但是如果你有 2% 的丟包率,那 HTTP2 在性能上就沒(méi)有優(yōu)勢(shì)了。
上圖是造成 TCP 隊(duì)頭擁塞(Head of line blocking)的原因。HTTP2 協(xié)議是基于 TCP 的,但是 TCP 本身是無(wú)法解決隊(duì)頭擁塞,為什么呢?因?yàn)?HTTP2 會(huì)把一次傳輸所有的文件都放在一個(gè) TCP 連接中,只要這個(gè) TCP 中發(fā)生一個(gè)丟包,連接就必須重新建立,之前所有傳輸內(nèi)容進(jìn)行必須重傳,從而造成擁塞。
HTTP3 VS HTTP2
-
HTTP3 本質(zhì)不是對(duì) HTTP 協(xié)議本身的改進(jìn),它主要是集中在如何提高傳輸效率。上圖是相比 HTTP2 而言 HTTP3 提升的點(diǎn):
-
HTTP3 使用 stream 進(jìn)一步擴(kuò)展了 HTTP2 的多路復(fù)用。在 HTTP3 模式下,一般傳輸多少個(gè)文件就會(huì)產(chǎn)生對(duì)應(yīng)數(shù)量的 stream。當(dāng)這些文件中的其中一個(gè)發(fā)生丟包時(shí),你只需要重傳丟包文件的對(duì)應(yīng) stream 即可。
-
HTTP3 不再是基于 TCP 建立的,而是通過(guò) UDP 建立,在用戶空間保證傳輸?shù)目煽啃?#xff0c;相比 TCP,UDP 之上的 QUIC 協(xié)議提高了連接建立的速度,降低了延遲。
-
通過(guò)引入 Connection ID,使得 HTTP3 支持連接遷移以及 NAT 的重綁定。
-
HTTP3 含有一個(gè)包括驗(yàn)證、加密、數(shù)據(jù)及負(fù)載的 built-in 的TLS安全機(jī)制。
-
擁塞控制。TCP 是在內(nèi)核區(qū)實(shí)現(xiàn)的,而 HTTP3 將擁塞控制移出了內(nèi)核,通過(guò)用戶空間來(lái)實(shí)現(xiàn)。這樣做的好處就是不再需要等待內(nèi)核更新可以實(shí)現(xiàn)很方便的進(jìn)行快速迭代。
-
頭部壓縮。HTTP2 使用的 HPACK,HTTP3 更換成了兼容 HPACK 的 QPACK 壓縮方案。QPACK 優(yōu)化了對(duì)亂序發(fā)送的支持,也優(yōu)化了壓縮率。
為什么選擇 QUIC
從圖上可以看到 QUIC 協(xié)議層就實(shí)現(xiàn)了可靠的數(shù)據(jù)傳輸,擁塞控制,加密,多路數(shù)據(jù)流。
至于 QUIC 為什么使用了 UDP 的問(wèn)題,在了解這個(gè)之前,我們需要先知道一個(gè)事情。頻繁的用戶態(tài)和核心態(tài)切換會(huì)效率問(wèn)題。理論上說(shuō),將應(yīng)用層的東西遷移到內(nèi)核從而提升效率是可行的,但是這么做會(huì)影響操作系統(tǒng)的穩(wěn)定性。另一方面,我們可以選擇將這部分內(nèi)容遷移到用戶空間。比如目前流行的 DPDK,當(dāng)網(wǎng)卡將數(shù)據(jù)包傳輸過(guò)來(lái)時(shí),它是繞過(guò)內(nèi)核在用戶空間進(jìn)行控制和應(yīng)用。目前又拍云的 DNS 就進(jìn)行了這樣的處理,讓又拍云的整體效率提升了5-10 倍。
接下來(lái)我們來(lái)正式說(shuō)一下 QUIC 為什么使用了 UDP 的問(wèn)題,是因?yàn)橐韵聨c(diǎn):
-
避免 ossification(僵化):QUIC 協(xié)議加密負(fù)載,也是避免協(xié)議僵化一種方式,比如當(dāng)中間層處理 UDP 數(shù)據(jù)時(shí),只需要按照數(shù)據(jù)包的方式去處理即可,不需要去關(guān)注內(nèi)部層的具體信息。
-
放棄改進(jìn) TCP 本身
-
創(chuàng)新方向:QUIC 是由谷歌提出的,所以 UDP 是以瀏覽器為出發(fā)點(diǎn),從協(xié)議、從瀏覽器方向來(lái)進(jìn)行創(chuàng)新。
TLS 1.3 Vs TLS 1.2
TLS 1.3 跟 1.2 的一些提升主要有上圖幾點(diǎn),大家可以大致看一下:
-
TLS 1.3 采用了新的加密套件
-
TLS 1.3 定義了一些新的證書類型以及秘鑰交換機(jī)制。在 TLS 1.3 你不再需要去特別指定,它可以根據(jù)秘鑰套件配件進(jìn)行證書類型的自主推導(dǎo)。
QUIC 存在的問(wèn)題
接下來(lái)說(shuō)一下 QUIC 目前存在的問(wèn)題。
首先是因?yàn)檫@些年性能的優(yōu)化提升都針對(duì) TCP ,使得 UDP 性能沒(méi)有任何改進(jìn)。當(dāng)然隨著 QUIC3 的發(fā)布,相信后續(xù)應(yīng)該會(huì)有相對(duì)的投入。
其次是安全問(wèn)題,也就是反射攻擊,即偽造原地址。這個(gè)指發(fā)送數(shù)據(jù)包時(shí)的原地址是偽造的,不是真正的地址,會(huì)引起放大攻擊。原因是 QUIC 握手過(guò)程是不對(duì)稱的,特別是第一次請(qǐng)求時(shí),客戶端只需要發(fā)送幾個(gè)字節(jié)的信息到服務(wù)器,而服務(wù)器則需要把證書等很多東西返還給客戶端,這個(gè)不對(duì)稱的機(jī)會(huì)造成了放大。草案 27 定義了兩個(gè)規(guī)則和機(jī)制來(lái)限制反射攻擊:客戶端發(fā)送Initial包,即第一個(gè)數(shù)據(jù)包時(shí),其長(zhǎng)度必須在 1200 bytes以上,不足部分用 Padding 幀填充,同時(shí),當(dāng)服務(wù)端不確定客戶端可靠性時(shí),可以發(fā)送 Retry 包要求客戶端再次提供驗(yàn)證信息。
開(kāi)源 QUIC 的實(shí)現(xiàn)
接下來(lái)我們簡(jiǎn)單說(shuō)一下目前開(kāi)源的使用情況:
-
quiche:這個(gè)是用 Rust 做的庫(kù),通過(guò) Nginx 調(diào)用。google 自己的庫(kù)也叫 quiche,C++寫的。
-
ATS:Apache Traffic Server
-
golang:Caddy;
-
python+C,aioquic
-
微軟msquic
開(kāi)源 QUIC 的實(shí)現(xiàn)有很多,上面只是其中的一部分,同時(shí)我選擇了quiche 和 aioquic 做了一些簡(jiǎn)單測(cè)試。
上圖展示的是從 cloudflare 提供支持 HTTP3 的 curl ,可以看到這個(gè)返回的值就是 HTTP/3 200。其中 alternative service 段,指示為 h3—27,表示支持 http3 draft-27 的服務(wù)跑在 UDP 443 端口。這個(gè) alt-svc 是 HTTP2 時(shí)代就存在,在 HTTP3 也持續(xù)使用,因?yàn)橛行r(shí)候?yàn)g覽器并不知道服務(wù)器是否支持 QUIC,所以通過(guò) TCP 發(fā)起請(qǐng)求,確定有 H3 支持后,再通過(guò) UDP連接。
這個(gè)是 HTTP2 的,目前可能是因?yàn)楸旧韼?kù)的問(wèn)題,使用 curl 打不開(kāi)谷歌,但是從信息上可以看到 27、25 這些都是支持的。
如何部署以及達(dá)成 HTTP3 的 QUIC 實(shí)現(xiàn)
目前主要有兩種方式來(lái)實(shí)現(xiàn),一種是代理,第二種是通過(guò) Nginx。
騰訊是通過(guò)整合到 Nginx 利用它來(lái)實(shí)現(xiàn)框架的。同時(shí)因?yàn)?QUIC 每一條請(qǐng)求的含有頭的數(shù)據(jù)都會(huì)經(jīng)過(guò)加密,騰訊有一個(gè)單獨(dú)的硬件加密群,如果你使用騰訊,那么你所有的加解密都會(huì)通過(guò)他們的硬件來(lái)加速。
從騰訊這個(gè)可以看出加解密部分有著很可觀的 CPU 占用率,如果后續(xù)所有的請(qǐng)求都是通過(guò) HTTP3 來(lái)進(jìn)行的話,在提升這塊占用率上需要未雨綢繆。當(dāng)然就像前面提到的 DPDK,也就是把數(shù)據(jù)丟到 FPGA 內(nèi)去加解密是一個(gè)可以考慮的解決方案。
通過(guò)代理來(lái)實(shí)現(xiàn)的這種方式,目前官方暫時(shí)還沒(méi)有消息。我可以像 cloudflare 那樣,先在外面進(jìn)行整合,然后再講整合鏈接轉(zhuǎn)到 Nginx 內(nèi)。
又拍云目前有 LBS 和 Marco ,這個(gè)是因?yàn)?LBS 只認(rèn) TCP/UDP,它看不到 HTTP。也就是我們做了一個(gè)負(fù)載均衡的集群,通過(guò)這個(gè)集群在轉(zhuǎn)到 Nginx 上。而使用 UDP 則相當(dāng)于已經(jīng)走過(guò)了一個(gè)四層的負(fù)載均衡,那么后續(xù)可以嘗試將 QUIC 的基線提取出來(lái)使用,在代理上做加解密,從而提高效率。
總結(jié)
以上是生活随笔為你收集整理的QUIC/HTTP3 协议简析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 从 301 跳转,聊聊边缘规则的那些小妙
- 下一篇: 原来!我在4年前就开始体验雾游戏了!