QUIC?協(xié)議在螞蟻金服落地
時間:2021-10-29 16:03:27
手機看文章
掃描二維碼
隨時隨地手機看文章
[導(dǎo)讀]大家好,我是小林。我之前寫過一篇介紹HTTP3的文章:看B站,可以更快!HTTP3協(xié)議最牛逼的地方在于,將傳輸層的TCP替換成UDP,而且還在UDP之上實現(xiàn)了可靠傳輸?shù)腝UIC協(xié)議。大家面試時如果被問到UDP如何實現(xiàn)可靠傳輸,就可以把QUIC協(xié)議的實現(xiàn)說出來,妥妥穩(wěn)的。這幾天看到...
大家好,我是小林。
我之前寫過一篇介紹 HTTP3 的文章:看 B 站,可以更快!
HTTP3協(xié)議最牛逼的地方在于,將傳輸層的 TCP 替換成 UDP,而且還在 UDP 之上實現(xiàn)了可靠傳輸?shù)?QUIC 協(xié)議。
大家面試時如果被問到 UDP 如何實現(xiàn)可靠傳輸,就可以把 QUIC 協(xié)議的實現(xiàn)說出來,妥妥穩(wěn)的。
這幾天看到一篇螞蟻集團(tuán)實戰(zhàn) QUIC 的文章,我覺得很不錯,特此分享給大家。
作者:孔令濤
【注】螞蟻 QUIC 開發(fā)團(tuán)隊包括:支付寶客戶端團(tuán)隊的梅男、蒼茫、述言,以及接入網(wǎng)關(guān)的伯琴、子荃、毅絲。
QUIC?背景介紹鑒于讀者的背景可能不同,在開始本文之前,我們先簡單介紹下 QUIC 相關(guān)的背景知識,如果您對這個協(xié)議的更多設(shè)計細(xì)節(jié)感興趣,可以參見相關(guān) Draft:https://datatracker.ietf.org/wg/quic/documents/
簡單來說,QUIC (Quick UDP Internet Connections) 是一種基于 UDP 封裝的安全? 可靠傳輸協(xié)議,他的目標(biāo)是取代 TCP 并自包含 TLS 成為標(biāo)準(zhǔn)的安全傳輸協(xié)議。下圖是 QUIC 在協(xié)議棧中的位置,基于 QUIC 承載的 HTTP 協(xié)議進(jìn)一步被標(biāo)準(zhǔn)化為 HTTP3.0。
在 QUIC 出現(xiàn)之前,TCP 承載了 90% 多的互聯(lián)網(wǎng)流量,似乎也沒什么問題,那又為何會出現(xiàn)革命者 QUIC 呢?這主要是因為發(fā)展了幾十年的 TCP 面臨 “協(xié)議僵化問題”,表現(xiàn)在幾方面:
下圖是 QUIC 從創(chuàng)建到現(xiàn)在為止的一些比較重要的時間節(jié)點,2021 年,QUIC V1 即將成為 RFC,結(jié)束百花齊放的態(tài)勢。
介紹完 QUIC 相關(guān)背景,之后我們來介紹螞蟻的整個落地的內(nèi)容,這里為了便于闡述,我們用螞蟻 QUIC 的 一、二、三、四 來進(jìn)行概括總結(jié),即 “一套落地框架”、“兩個落地場景”、“三篇創(chuàng)新專利保護(hù)”、“四項關(guān)鍵技術(shù)”。
一套落地框架螞蟻的接入網(wǎng)關(guān)是基于多進(jìn)程的 NGINX 開發(fā)的 (內(nèi)部稱為 Spanner,協(xié)議卸載的扳手),而 UDP 在多進(jìn)程編程模型上存在諸多挑戰(zhàn),典型的像無損升級等。為了設(shè)計一套完備的框架,我們在落地前充分考慮了服務(wù)端在云上部署上的方便性、擴(kuò)展性、以及性能問題,設(shè)計了如下的落地框架以支撐不同的落地場景:在這套框架中,包括如下兩個組件:
當(dāng)前框架支持的能力包括如下:
為何能支持上述能力,我們后面會展開敘述
兩個落地場景
我們由近及遠(yuǎn)的兩個落地場景如下:
場景一、支付寶移動端落地
如下為我們落地架構(gòu)的示意圖,支付寶手機客戶端通過 QUIC 攜帶 HTTP 請求,通過 QUIC LB 等四層網(wǎng)關(guān)將請求轉(zhuǎn)發(fā)到 Spanner (螞蟻內(nèi)部基于 NGINX 開發(fā)的 7 層網(wǎng)關(guān)),在 Spanner 上我們將 QUIC 請求 Proxy 成 TCP 請求,發(fā)送給業(yè)務(wù)網(wǎng)關(guān)(RS)。
具體的方案選型如下:
場景二、海外加速落地螞蟻集團(tuán)從 2018 年開始自研了海外的動態(tài)加速平臺 AGNA(Ant Global Network Accelerator)以替換第三方廠商的加速服務(wù)。AGNA 通過在海外部署接入點:Local Proxy(LP) 以及在國內(nèi)部署接出點:Remote Proxy (RP)的方式,將用戶的海外請求通過 LP 和 RP 的加速鏈路回源國內(nèi)。如下圖所示,我們將 QUIC 部署在 LP 和 RP 之間的鏈路。
在海外接入點上(LP),每一個 TCP 連接都被 Proxy 成 QUIC 上的一個 Stream 進(jìn)行承載,在國內(nèi)接出點上(RP), 每一個 QUIC Stream 又被 Proxy 成一個 TCP 連接,LP 和 RP 之間使用 QUIC 長連接。
在此場景下,通過使用 QUIC 可以獲得的紅利包括:
三篇關(guān)鍵專利
到目前為止,我們把落地過程中一些創(chuàng)新的技術(shù)點通過申請專利進(jìn)行了保護(hù),并積極在 IETF 進(jìn)行標(biāo)準(zhǔn)化分享我們的研究成果,包括:
我們將落地場景 2 中,通過 QUIC Stream 進(jìn)行四層代理的手段來進(jìn)行海外回源的加速方法進(jìn)行專利保護(hù),提出:“一種基于 QUIC 協(xié)議代理的的鏈路加速方法”,目前此專利已經(jīng)獲得美國專利授權(quán),專利號:CN110213241A。
將我們落地框架中的 QUIC LB 組件作為專利進(jìn)行保護(hù),提出:“一種無狀態(tài)、一致性、分布式的 QUIC 負(fù)載均衡設(shè)備”,目前此專利還在受理中。由于通過 QUIC LB 可以很好的支持 QUIC 協(xié)議的連接遷移問題,所以目前 IETF QUIC WG 上有關(guān)于 QUIC LB 相關(guān)的草案,我們目前已經(jīng)參與到 Draft 的討論和制定中,后序相關(guān)的方案也會繼續(xù)推廣到云上產(chǎn)品。
將我們解決的 UDP 的無損升級方法進(jìn)行專利保護(hù),提出 “一種 QUIC 服務(wù)器無損升級方案”,目前此專利還在受理中。由于 UDP 無損升級問題是一個業(yè)界難題,當(dāng)前有些手段需要在用戶態(tài)進(jìn)行跳轉(zhuǎn),性能損失較大,我們的方案可以在我們的落地框架中解決當(dāng)前問題,關(guān)于這個方案的細(xì)節(jié)我們再后面的關(guān)鍵技術(shù)中進(jìn)行介紹。
四項關(guān)鍵技術(shù)
在整個的落地中,我們設(shè)計的方案圍繞解決幾個核心問題展開,形成了四項關(guān)鍵技術(shù),分別如下
如下圖所示,是 QUIC 支持連接的一個示意圖,當(dāng)客戶端出口地址從 A 切換成 B 的時候,因為 CID 保持不變,所以在 QUIC 服務(wù)器上,依然可以查詢到對應(yīng)的 Session 狀態(tài)。
然而,理論很豐滿,落地卻很艱難,在端到端的落地過程中,因為引入了負(fù)載均衡設(shè)備,會導(dǎo)致在連接遷移時,所有依賴五元組 Hash 做轉(zhuǎn)發(fā)或者關(guān)聯(lián) Session 的機制失效。以 LVS 為例,連接遷移后, LVS 依靠五元組尋址會導(dǎo)致尋址的服務(wù)器存在不一致。即便 LVS 尋址正確,當(dāng)報文到達(dá)服務(wù)器時,內(nèi)核根據(jù)五元組關(guān)聯(lián)進(jìn)程,依然會尋址出錯。同時,IETF Draft 要求,連接遷移時 CID 需要更新掉,這就為僅依靠 CID 來轉(zhuǎn)發(fā)的計劃同樣變的不可行。
而 UDP 無法做到無損升級是因為 UDP 只有一個 listening socket 沒有類似 TCP 的連接套接字,所有的收發(fā)數(shù)據(jù)包都在這個 socket 上,導(dǎo)致下面的熱升級步驟會存在問題:
盡管落地 QUIC 的愿望是好的,但是新事物的發(fā)展并不是一帆風(fēng)順的。由于 QUIC 是基于 UDP 的,而 UDP 相比于 TCP 在運營商的支持上并非友好,表現(xiàn)在:
做個總結(jié)
本文主要綜述性的介紹了 QUIC 在螞蟻的落地方案、場景以及一些關(guān)鍵技術(shù)。關(guān)鍵技術(shù)上,主要介紹了我們?nèi)绾瓮ㄟ^創(chuàng)造性的提出 QUIC LB 組件、以及多端口監(jiān)聽的機制來優(yōu)雅的支持?QUIC 的連接遷移機制、QUIC 服務(wù)端的無損升級等,依賴這套方案我們的接入網(wǎng)關(guān)不需要像業(yè)界一樣依賴底層內(nèi)核的改動,這極大的方便了我們方案的部署,尤其在公有云場景下。除了連接遷移以外,我們還提出了 0RTT 建聯(lián)提升方案、客戶端智能選路方案,以最大化 QUIC 在移動端上的收益。截止當(dāng)前,QUIC 已經(jīng)在支付寶移動端以及全球加速鏈路兩個場景上平穩(wěn)運行,并帶來了較好的業(yè)務(wù)收益。
未來規(guī)劃
兩年來,我們主要以社區(qū)的 gQuic 為基礎(chǔ),充分發(fā)揮 QUIC 的協(xié)議優(yōu)勢,并結(jié)合螞蟻的業(yè)務(wù)特征以最大化移動端收益為目標(biāo),創(chuàng)造性的提出了一些解決方案,并積極向社區(qū)和 IETF 進(jìn)行推廣。在未來,隨著螞蟻在更多業(yè)務(wù)上的開展和探索以及HTTP3.0/QUIC 即將成為標(biāo)準(zhǔn),我們會主要圍繞以下幾個方向繼續(xù)深挖 QUIC 的價值:
??
我之前寫過一篇介紹 HTTP3 的文章:看 B 站,可以更快!
HTTP3協(xié)議最牛逼的地方在于,將傳輸層的 TCP 替換成 UDP,而且還在 UDP 之上實現(xiàn)了可靠傳輸?shù)?QUIC 協(xié)議。
大家面試時如果被問到 UDP 如何實現(xiàn)可靠傳輸,就可以把 QUIC 協(xié)議的實現(xiàn)說出來,妥妥穩(wěn)的。
這幾天看到一篇螞蟻集團(tuán)實戰(zhàn) QUIC 的文章,我覺得很不錯,特此分享給大家。
作者:孔令濤
自 2015 年以來,QUIC 協(xié)議開始在 IETF 進(jìn)行標(biāo)準(zhǔn)化并被國內(nèi)外各大廠商相繼落地。鑒于 QUIC 具備“0RTT 建聯(lián)”、“支持連接遷移”等諸多優(yōu)勢,并將成為下一代互聯(lián)網(wǎng)協(xié)議:HTTP3.0 的底層傳輸協(xié)議,螞蟻集團(tuán)支付寶客戶端團(tuán)隊與接入網(wǎng)關(guān)團(tuán)隊于 2018 年下半年開始在移動支付、海外加速等場景落地 QUIC。本文是綜述篇,介紹?QUIC?在螞蟻的整體落地情況。之所以是綜述,是因為 QUIC 協(xié)議過于復(fù)雜,如果對標(biāo)已有的協(xié)議,QUIC 近似等于 HTTP TLS TCP,無法詳細(xì)的畢其功于一役,因此我們通過綜述的方式將落地的重點呈現(xiàn)給讀者,主要介紹如下幾個部分:
- QUIC背景:簡單全面的介紹下 QUIC 相關(guān)的背景知識
- 方案選型設(shè)計:詳細(xì)介紹螞蟻的落地方案如何另辟蹊徑、優(yōu)雅的支撐 QUIC 的諸多特性,包括連接遷移等
- 落地場景:介紹 QUIC 在螞蟻的兩個落地場景,包括:支付寶客戶端鏈路以及海外加速鏈路
- 幾項關(guān)鍵技術(shù):介紹落地 QUIC 過程中核心需要解決的問題,以及我們使用的方案,包括:“支持連接遷移”、“提升 0RTT 比例", "支持 UDP 無損升級”以及“客戶端智能選路”?等
- 幾項關(guān)鍵的技術(shù)專利
【注】螞蟻 QUIC 開發(fā)團(tuán)隊包括:支付寶客戶端團(tuán)隊的梅男、蒼茫、述言,以及接入網(wǎng)關(guān)的伯琴、子荃、毅絲。
QUIC?背景介紹鑒于讀者的背景可能不同,在開始本文之前,我們先簡單介紹下 QUIC 相關(guān)的背景知識,如果您對這個協(xié)議的更多設(shè)計細(xì)節(jié)感興趣,可以參見相關(guān) Draft:https://datatracker.ietf.org/wg/quic/documents/
一、QUIC 是什么?
簡單來說,QUIC (Quick UDP Internet Connections) 是一種基于 UDP 封裝的安全? 可靠傳輸協(xié)議,他的目標(biāo)是取代 TCP 并自包含 TLS 成為標(biāo)準(zhǔn)的安全傳輸協(xié)議。下圖是 QUIC 在協(xié)議棧中的位置,基于 QUIC 承載的 HTTP 協(xié)議進(jìn)一步被標(biāo)準(zhǔn)化為 HTTP3.0。
二、為什么是 QUIC ?
在 QUIC 出現(xiàn)之前,TCP 承載了 90% 多的互聯(lián)網(wǎng)流量,似乎也沒什么問題,那又為何會出現(xiàn)革命者 QUIC 呢?這主要是因為發(fā)展了幾十年的 TCP 面臨 “協(xié)議僵化問題”,表現(xiàn)在幾方面:
- 網(wǎng)絡(luò)設(shè)備支持 TCP 時的僵化,表現(xiàn)在:對于一些防火墻或者 NAT 等設(shè)備,如果 TCP 引入了新的特性,比如增加了某些 TCP OPTION 等,可能會被認(rèn)為是攻擊而丟包,導(dǎo)致新特性在老的網(wǎng)絡(luò)設(shè)備上無法工作。
- 網(wǎng)絡(luò)操作系統(tǒng)升級困難導(dǎo)致的 TCP 僵化,一些 TCP 的特性無法快速的被演進(jìn)。
- 除此之外,當(dāng)應(yīng)用層協(xié)議優(yōu)化到 TLS1.3、 HTTP2.0 后, 傳輸層的優(yōu)化也提上了議程,QUIC 在 TCP 基礎(chǔ)上,取其精華去其糟粕具有如下的硬核優(yōu)勢:
三、QUIC 生態(tài)圈發(fā)展簡史
下圖是 QUIC 從創(chuàng)建到現(xiàn)在為止的一些比較重要的時間節(jié)點,2021 年,QUIC V1 即將成為 RFC,結(jié)束百花齊放的態(tài)勢。
介紹完 QUIC 相關(guān)背景,之后我們來介紹螞蟻的整個落地的內(nèi)容,這里為了便于闡述,我們用螞蟻 QUIC 的 一、二、三、四 來進(jìn)行概括總結(jié),即 “一套落地框架”、“兩個落地場景”、“三篇創(chuàng)新專利保護(hù)”、“四項關(guān)鍵技術(shù)”。
一套落地框架螞蟻的接入網(wǎng)關(guān)是基于多進(jìn)程的 NGINX 開發(fā)的 (內(nèi)部稱為 Spanner,協(xié)議卸載的扳手),而 UDP 在多進(jìn)程編程模型上存在諸多挑戰(zhàn),典型的像無損升級等。為了設(shè)計一套完備的框架,我們在落地前充分考慮了服務(wù)端在云上部署上的方便性、擴(kuò)展性、以及性能問題,設(shè)計了如下的落地框架以支撐不同的落地場景:在這套框架中,包括如下兩個組件:
- QUIC LB 組件:基于 NGINX 4層 UDP Stream 模塊開發(fā),用來基于 QUIC DCID 中攜帶的服務(wù)端信息進(jìn)行路由,以支持連接遷移。
- NGINX QUIC 服務(wù)器:開發(fā)了 NGINX_QUIC_MODULE,每個 Worker 監(jiān)聽兩種類型的端口:(1)BASE PORT ,每個 Worker 使用的相同的端口號,以 Reuseport 的形式監(jiān)聽,并暴露給 QUIC LB,用以接收客戶端過來的第一個 RTT 中的數(shù)據(jù)包,這類包的特點是 DCID 由客戶端生成,沒有路由信息。(2)Working PORT,每個 Worker 使用的不同的端口號,是真正的工作端口,用以接收第一個 RTT 之后的 QUIC 包,這類包的特定是 DCID 由服務(wù)端的進(jìn)程生成攜帶有服務(wù)端的信息。
當(dāng)前框架支持的能力包括如下:
- 在不用修改內(nèi)核的情況下,完全在用戶態(tài)支持 QUIC 的連接遷移,以及連接遷移時 CID 的 Update
- 在不用修改內(nèi)核的情況下,完全在用戶態(tài)支持 QUIC 的無損升級以及其他運維問題
- 支持真正意義上的 0RTT ,并可提升 0RTT 的比例
為何能支持上述能力,我們后面會展開敘述
兩個落地場景
我們由近及遠(yuǎn)的兩個落地場景如下:
場景一、支付寶移動端落地
如下為我們落地架構(gòu)的示意圖,支付寶手機客戶端通過 QUIC 攜帶 HTTP 請求,通過 QUIC LB 等四層網(wǎng)關(guān)將請求轉(zhuǎn)發(fā)到 Spanner (螞蟻內(nèi)部基于 NGINX 開發(fā)的 7 層網(wǎng)關(guān)),在 Spanner 上我們將 QUIC 請求 Proxy 成 TCP 請求,發(fā)送給業(yè)務(wù)網(wǎng)關(guān)(RS)。
具體的方案選型如下:
- 支持的 QUIC 版本是 gQUIC Q46。
- NGINX QUIC MODULE 支持 QUIC 的接入和 PROXY 成 TCP 的能力。
- 支持包括移動支付、基金、螞蟻森林在內(nèi)的所有的 RPC 請求。
- 當(dāng)前選擇 QUIC 鏈路的方式有兩種 :
- Backup 模式,即在 TCP 鏈路無法使用的情況下,降級到 QUIC 鏈路。
- Smart 模式,即 TCP和 QUIC 競速,在 TCP 表現(xiàn)力弱于 QUIC 的情況下,下次請求主動使用 QUIC 鏈路。
- 在客戶端連接發(fā)生遷移的時候,可以不斷鏈繼續(xù)服務(wù)
- 客戶端在首次發(fā)起連接時,可以節(jié)省 TCP 三次握手的時間
- 對于弱網(wǎng)情況,QUIC 的傳輸控制可以帶來傳輸性能提升
場景二、海外加速落地螞蟻集團(tuán)從 2018 年開始自研了海外的動態(tài)加速平臺 AGNA(Ant Global Network Accelerator)以替換第三方廠商的加速服務(wù)。AGNA 通過在海外部署接入點:Local Proxy(LP) 以及在國內(nèi)部署接出點:Remote Proxy (RP)的方式,將用戶的海外請求通過 LP 和 RP 的加速鏈路回源國內(nèi)。如下圖所示,我們將 QUIC 部署在 LP 和 RP 之間的鏈路。
在海外接入點上(LP),每一個 TCP 連接都被 Proxy 成 QUIC 上的一個 Stream 進(jìn)行承載,在國內(nèi)接出點上(RP), 每一個 QUIC Stream 又被 Proxy 成一個 TCP 連接,LP 和 RP 之間使用 QUIC 長連接。
在此場景下,通過使用 QUIC 可以獲得的紅利包括:
- 通過 QUIC 長連接的上的 Stream 承載 TCP 請求,避免每次的跨海建聯(lián)。
- 對于跨海的網(wǎng)絡(luò),QUIC 的傳輸控制可以帶來傳輸性能提升。
三篇關(guān)鍵專利
到目前為止,我們把落地過程中一些創(chuàng)新的技術(shù)點通過申請專利進(jìn)行了保護(hù),并積極在 IETF 進(jìn)行標(biāo)準(zhǔn)化分享我們的研究成果,包括:
專利一
我們將落地場景 2 中,通過 QUIC Stream 進(jìn)行四層代理的手段來進(jìn)行海外回源的加速方法進(jìn)行專利保護(hù),提出:“一種基于 QUIC 協(xié)議代理的的鏈路加速方法”,目前此專利已經(jīng)獲得美國專利授權(quán),專利號:CN110213241A。
專利二
將我們落地框架中的 QUIC LB 組件作為專利進(jìn)行保護(hù),提出:“一種無狀態(tài)、一致性、分布式的 QUIC 負(fù)載均衡設(shè)備”,目前此專利還在受理中。由于通過 QUIC LB 可以很好的支持 QUIC 協(xié)議的連接遷移問題,所以目前 IETF QUIC WG 上有關(guān)于 QUIC LB 相關(guān)的草案,我們目前已經(jīng)參與到 Draft 的討論和制定中,后序相關(guān)的方案也會繼續(xù)推廣到云上產(chǎn)品。
專利三
將我們解決的 UDP 的無損升級方法進(jìn)行專利保護(hù),提出 “一種 QUIC 服務(wù)器無損升級方案”,目前此專利還在受理中。由于 UDP 無損升級問題是一個業(yè)界難題,當(dāng)前有些手段需要在用戶態(tài)進(jìn)行跳轉(zhuǎn),性能損失較大,我們的方案可以在我們的落地框架中解決當(dāng)前問題,關(guān)于這個方案的細(xì)節(jié)我們再后面的關(guān)鍵技術(shù)中進(jìn)行介紹。
四項關(guān)鍵技術(shù)
在整個的落地中,我們設(shè)計的方案圍繞解決幾個核心問題展開,形成了四項關(guān)鍵技術(shù),分別如下
技術(shù)點1.優(yōu)雅的支持連接遷移能力
先說?連接遷移面臨的問題 ,上文有提到,QUIC 有一項比較重要的功能是支持連接遷移。這里的連接遷移是指:如果客戶端在長連接保持的情況下切換網(wǎng)絡(luò),比如從 4G 切換到 Wifi , 或者因為 NAT Rebinding 導(dǎo)致五元組發(fā)生變化,QUIC 依然可以在新的五元組上繼續(xù)進(jìn)行連接狀態(tài)。QUIC 之所以能支持連接遷移,一個原因是 QUIC 底層是基于無連接的 UDP,另一個重要原因是因為 QUIC 使用唯一的 CID 來標(biāo)識一個連接,而不是五元組。
如下圖所示,是 QUIC 支持連接的一個示意圖,當(dāng)客戶端出口地址從 A 切換成 B 的時候,因為 CID 保持不變,所以在 QUIC 服務(wù)器上,依然可以查詢到對應(yīng)的 Session 狀態(tài)。
然而,理論很豐滿,落地卻很艱難,在端到端的落地過程中,因為引入了負(fù)載均衡設(shè)備,會導(dǎo)致在連接遷移時,所有依賴五元組 Hash 做轉(zhuǎn)發(fā)或者關(guān)聯(lián) Session 的機制失效。以 LVS 為例,連接遷移后, LVS 依靠五元組尋址會導(dǎo)致尋址的服務(wù)器存在不一致。即便 LVS 尋址正確,當(dāng)報文到達(dá)服務(wù)器時,內(nèi)核根據(jù)五元組關(guān)聯(lián)進(jìn)程,依然會尋址出錯。同時,IETF Draft 要求,連接遷移時 CID 需要更新掉,這就為僅依靠 CID 來轉(zhuǎn)發(fā)的計劃同樣變的不可行。
再說?我們的解決方法,為了解決此問題,我們設(shè)計了開篇介紹的落地框架,這里我們將方案做一些簡化和抽象,整體思路如下圖所示:
- 在四層負(fù)載均衡上,我們設(shè)計了 QUIC LoadBalancer 的機制:
- 我們在 QUIC 的 CID 中擴(kuò)展了一些字段(ServerInfo)用來關(guān)聯(lián) QUIC Server 的 IP 和 Working Port 信息。
- 在發(fā)生連接遷移的時候,QUIC LoadBalancer 可以依賴 CID 中的 ServerInfo 進(jìn)行路由,避免依賴五元組關(guān)聯(lián) Session 導(dǎo)致的問題。
- 在 CID 需要 Update 的時候,NewCID 中的 ServerInfo 保留不變,這樣就避免在 CID 發(fā)生 Update 時,僅依賴 CID Hash 挑選后端導(dǎo)致的尋址不一致問題。
- 在 QUIC 服務(wù)器多進(jìn)程工作模式上,我們突破了 NGINX 固有的多 Worker 監(jiān)聽在相同端口上的桎梏,設(shè)計了多端口監(jiān)聽的機制,每個 Worker 在工作端口上進(jìn)行隔離,并將端口的信息攜帶在對 First Initial Packet 的回包的 CID 中,這樣代理的好處是:
- 無論是否連接遷移,QUIC LB 都可以根據(jù) ServerInfo,將報文轉(zhuǎn)發(fā)到正確的進(jìn)程。
- 而業(yè)界普遍的方案是修改內(nèi)核,將 Reuse port 機制改為 Reuse CID 機制,即內(nèi)核根據(jù) CID 挑選進(jìn)程。即便后面可以通過 ebpf 等手段支持,但我們認(rèn)為這種修改內(nèi)核的機制對底層過于依賴,不利于方案的大規(guī)模部署和運維,尤其在公有云上。
- 使用獨立端口,也有利于多進(jìn)程模式下,UDP 無損升級問題的解決,這個我們在技術(shù)點 3 中介紹。
這里先?介紹 QUIC 0RTT 原理。前文我們介紹過, QUIC 支持傳輸層握手和安全加密層握手都在一個 0RTT 內(nèi)完成。TLS1.3 本身就支持加密層握手的 0RTT,所以不足為奇。而 QUIC 如何實現(xiàn)傳輸層握手支持 0RTT 呢?我們先看下傳輸層握手的目的,即:服務(wù)端校驗客戶端是真正想握手的客戶端,地址不存在欺騙,從而避免偽造源地址攻擊。在 TCP 中,服務(wù)端依賴三次握手的最后一個 ACK 來校驗客戶端是真正的客戶端,即只有真正的客戶端才會收到 Sever 的 syn_ack 并回復(fù)。
QUIC 同樣需要對握手的源地址做校驗,否則便會存在 UDP 本身的 DDOS 問題,那 QUIC 是如何實現(xiàn)的?依賴 STK(Source Address Token) 機制。這里我們先聲明下,跟 TLS 類似,QUIC 的 0RTT 握手,是建立在已經(jīng)同一個服務(wù)器建立過連接的基礎(chǔ)上,所以如果是純的第一次連接,仍然需要一個 RTT 來獲取這個 STK。如下圖所示,我們介紹下這個原理:- 類似于 Session Ticket 原理,Server 會將客戶端的地址和當(dāng)前的 Timestamp 通過自己的 KEY 加密生成 STK。
- Client 下次握手的時候,將 STK 攜帶過來,由于 STK 無法篡改,所以 Server 通過自己的 KEY 解密,如果解出來的地址和客戶端此次握手的地址一致,且時間在有效期內(nèi),則表示客戶端可信,便可以建立連接。
- 由于客戶端第一次握手的時候,沒有這個 STK,所以服務(wù)度會回復(fù) REJ 這次握手的信息,并攜帶 STK。
- 因為 STK 是服務(wù)端加密的,所以如果下次這個客戶端路由到別的服務(wù)器上了,則這個服務(wù)器也需要可以識別出來。
- STK 中 encode 的是上一次客戶端的地址,如果下一次客戶端攜帶的地址發(fā)生了變化,則同樣會導(dǎo)致校驗失敗。此現(xiàn)象在移動端發(fā)生的概率非常大,尤其是 IPV6 場景下,客戶端的出口地址會經(jīng)常發(fā)生變化。
再介紹下我們的解決方法。第一個問題比較好解,我們只要保證集群內(nèi)的機器生成 STK 的秘鑰一致即可。第二個問題,我們的解題思路是:
- 我們在 STK 中擴(kuò)展了一個 Client ID, 這個 Clinet ID 是客戶端通過無線保鏢黑盒生成并全局唯一不變的,類似于一個設(shè)備的 SIMID,客戶端通過加密的 Trasnport Parameter 傳遞給服務(wù)端,服務(wù)端在 STK 中包含這個 ID。
- 如果因為 Client IP 發(fā)生變化導(dǎo)致校驗 STK 校驗失敗,便會去校驗 Client ID,因為 ID 對于一個 Client 是永遠(yuǎn)不變的,所以可以校驗成功,當(dāng)然前提是,這個客戶端是真實的。為了防止 Client ID 的泄露等,我們會選擇性對 Client ID 校驗?zāi)芰ψ鱿蘖鞅Wo(hù)。
技術(shù)點3. 支持 QUIC 無損升級
我們知道?UDP 無損升級是業(yè)界難題。無損升級是指在 reload 或者更新二進(jìn)制時,老的進(jìn)程可以處理完存量連接上的數(shù)據(jù)后優(yōu)雅退出。以 NGINX 為例,這里先介紹下 TCP 是如何處理無損升級的,主要是如下的兩個步驟:
- 老進(jìn)程先關(guān)閉 listening socket,待存量連接請求都結(jié)束后,再關(guān)閉連接套接字
- 新進(jìn)程從老進(jìn)程繼承 listening socket , 開始 accept 新的請求
而 UDP 無法做到無損升級是因為 UDP 只有一個 listening socket 沒有類似 TCP 的連接套接字,所有的收發(fā)數(shù)據(jù)包都在這個 socket 上,導(dǎo)致下面的熱升級步驟會存在問題:
- 在熱升級的時候,old process fork 出 new process 后,new process 會繼承 listening socket 并開始 recv msg。
- 而 old process 此時如果關(guān)閉 listenging socket, 則在途的數(shù)據(jù)包便無法接收,達(dá)不到優(yōu)雅退出的目的。
- 而如果繼續(xù)監(jiān)聽,則新老進(jìn)程都會同時收取新連接上的報文,導(dǎo)致老進(jìn)程無法退出。
這里介紹下相關(guān)的解決方法。針對此問題,業(yè)界有一些方法,比如:在數(shù)據(jù)包中攜帶進(jìn)程號,當(dāng)數(shù)據(jù)包收發(fā)錯亂后,在新老進(jìn)程之間做一次轉(zhuǎn)發(fā)??紤]到接入層上的性能等原因,我們不希望數(shù)據(jù)再做一次跳轉(zhuǎn)。結(jié)合我們的落地架構(gòu),我們設(shè)計了如下的?基于多端口輪轉(zhuǎn)的無損升級方案,簡單來說,我們讓新老進(jìn)程監(jiān)聽在不同的端口組并攜帶在 CID 中,這樣 QUIC LB 就可以根據(jù)端口轉(zhuǎn)發(fā)到新老進(jìn)程。為了便于運維,我們采用端口輪轉(zhuǎn)的方式,新老進(jìn)程會在 reload N 次之后,重新開始之前選中的端口。如下圖所示:
- 無損升級期間,老進(jìn)程的 Baseport 端口關(guān)閉,這樣不會再接受 first intial packet, 類似于關(guān)閉了 tcp 的 listening socket。
- 老進(jìn)程的工作端口,繼續(xù)工作,用來接收當(dāng)前進(jìn)程上殘余的流量。
- 新進(jìn)程的 Baseport 開始工作,用來接收 first initial packet, 開啟新的連接,類似于開啟了 tcp 的 listening socket。
- 新進(jìn)程的 working port = (I 1) mod N, ?N 是指同時支持新老進(jìn)程的狀態(tài)的次數(shù),例如 N = 4, 表示可以同時 reload 四次,四種 Old, New1, New2, New3 四種狀態(tài)同時并存,I 是上一個進(jìn)程工作的端口號,這里 1 是因為只有一個 worker, 如果 worker 數(shù)有 M 個,則加 M。
- 建好的連接便被 Load Balancer 轉(zhuǎn)移到新進(jìn)程的監(jiān)聽端口的 Working Port 上。
盡管落地 QUIC 的愿望是好的,但是新事物的發(fā)展并不是一帆風(fēng)順的。由于 QUIC 是基于 UDP 的,而 UDP 相比于 TCP 在運營商的支持上并非友好,表現(xiàn)在:
- 在帶寬緊張的時候,UDP 會經(jīng)常被限流。
- 一些防火墻對于 UDP 包會直接 Drop。
- NAT 網(wǎng)關(guān)針對 UDP 的 Session 存活時間也較短。
做個總結(jié)
本文主要綜述性的介紹了 QUIC 在螞蟻的落地方案、場景以及一些關(guān)鍵技術(shù)。關(guān)鍵技術(shù)上,主要介紹了我們?nèi)绾瓮ㄟ^創(chuàng)造性的提出 QUIC LB 組件、以及多端口監(jiān)聽的機制來優(yōu)雅的支持?QUIC 的連接遷移機制、QUIC 服務(wù)端的無損升級等,依賴這套方案我們的接入網(wǎng)關(guān)不需要像業(yè)界一樣依賴底層內(nèi)核的改動,這極大的方便了我們方案的部署,尤其在公有云場景下。除了連接遷移以外,我們還提出了 0RTT 建聯(lián)提升方案、客戶端智能選路方案,以最大化 QUIC 在移動端上的收益。截止當(dāng)前,QUIC 已經(jīng)在支付寶移動端以及全球加速鏈路兩個場景上平穩(wěn)運行,并帶來了較好的業(yè)務(wù)收益。
未來規(guī)劃
兩年來,我們主要以社區(qū)的 gQuic 為基礎(chǔ),充分發(fā)揮 QUIC 的協(xié)議優(yōu)勢,并結(jié)合螞蟻的業(yè)務(wù)特征以最大化移動端收益為目標(biāo),創(chuàng)造性的提出了一些解決方案,并積極向社區(qū)和 IETF 進(jìn)行推廣。在未來,隨著螞蟻在更多業(yè)務(wù)上的開展和探索以及HTTP3.0/QUIC 即將成為標(biāo)準(zhǔn),我們會主要圍繞以下幾個方向繼續(xù)深挖 QUIC 的價值:
- 我們將利用 QUIC 在應(yīng)用層實現(xiàn)的優(yōu)勢,設(shè)計一套統(tǒng)一的具備自適應(yīng)業(yè)務(wù)類型和網(wǎng)絡(luò)類型的 QUIC 傳輸控制框架,對不同類型的業(yè)務(wù)和網(wǎng)絡(luò)類型,做傳輸上的調(diào)優(yōu),以優(yōu)化業(yè)務(wù)的網(wǎng)絡(luò)傳輸體驗。
- 將 gQUIC 切換成 IETF QUIC,推進(jìn)標(biāo)準(zhǔn)的 HTTP3.0 在螞蟻的進(jìn)一步落地。
- 將螞蟻的 QUIC LB 技術(shù)點向 IETF QUIC LB 進(jìn)行推進(jìn),并最終演變?yōu)闃?biāo)準(zhǔn)的 QUIC LB。
- 探索并落地 MPQUIC(多路徑 QUIC)?技術(shù),最大化在移動端的收益。
- 繼續(xù) QUIC 的性能優(yōu)化工作,使用 UDP GSO, eBPF,io_uring 等內(nèi)核技術(shù)。
- 探索 QUIC 在內(nèi)網(wǎng)承載東西向流量的機會。