自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Trip.com QUIC 高可用及性能提升

開發(fā) 網(wǎng)絡(luò)
本文詳細(xì)介紹了QUIC協(xié)議在攜程 Trip.com App上的實(shí)踐方案,以及團(tuán)隊(duì)在QUIC高可用及性能提升方面所做的各類優(yōu)化。

首先介紹了QUIC多進(jìn)程部署架構(gòu),隨后分析了QUIC網(wǎng)絡(luò)架構(gòu)在生產(chǎn)應(yīng)用中遇到的問題及其優(yōu)化方案。在性能提升方面,分享了QUIC全鏈路埋點(diǎn)監(jiān)控的實(shí)現(xiàn)思路及其收獲,QUIC擁塞控制算法開發(fā)與調(diào)優(yōu)思路等等。希望這些內(nèi)容能夠幫助大家了解QUIC協(xié)議及其在實(shí)際應(yīng)用中的優(yōu)化思路,并從中獲得啟發(fā)。

一、前言

1.1 QUIC在Trip.com APP的落地簡(jiǎn)介

QUIC(Quick UDP Internet Connections)是由Google提出的基于UDP的傳輸層協(xié)議,為HTTP3的標(biāo)準(zhǔn)傳輸層協(xié)議。相較于TCP協(xié)議,QUIC主要具備以下優(yōu)勢(shì):

1)多路復(fù)用:QUIC允許在單個(gè)連接上并行傳輸多個(gè)數(shù)據(jù)流,解決了TCP的隊(duì)頭阻塞問題,從而提高了傳輸效率;

2)快速建連:新建連時(shí),QUIC握手與TLS握手并行,避免了TLS單獨(dú)握手所消耗的1個(gè)RTT時(shí)延。當(dāng)用戶連接過期失效且在PSK(pre-shared key)有效期內(nèi)再次建連時(shí),QUIC通過驗(yàn)證PSK復(fù)用TLS會(huì)話,實(shí)現(xiàn)0-RTT建聯(lián),從而可以更快的建立連接,此特性在短連接,單用戶低頻請(qǐng)求的場(chǎng)景中收益尤為明顯;

3)連接遷移:TCP通過四元組標(biāo)識(shí)一個(gè)連接,當(dāng)四元組中的任一部分發(fā)生變化時(shí),連接都會(huì)失效。而QUIC通過連接CID唯一標(biāo)識(shí)一個(gè)連接,當(dāng)用戶網(wǎng)絡(luò)發(fā)生切換(例如WIFI切換到4G)時(shí),QUIC依然可以通過CID找到連接,完成新路徑驗(yàn)證繼續(xù)保持連接通信,避免重新建連帶來的耗時(shí);

4)擁塞控制:TCP的擁塞控制需要操作系統(tǒng)的支持,部署成本高,升級(jí)周期長(zhǎng),而QUIC在應(yīng)用層實(shí)現(xiàn)擁塞控制算法,升級(jí)變更加靈活;

上述優(yōu)質(zhì)特性推動(dòng)了QUIC協(xié)議在IETF的標(biāo)準(zhǔn)化發(fā)展,2021年5月,IETF推出了QUIC的標(biāo)準(zhǔn)化版本RFC9000,我們于2022年完成了QUIC多進(jìn)程部署方案在Trip.com APP的落地,支持了多進(jìn)程下的連接遷移和0-RTT特性,最終取得了Trip.com App鏈路耗時(shí)縮短20%的收益,大大的提升了海外用戶的體驗(yàn)。我們的初期網(wǎng)絡(luò)架構(gòu)如下:

圖片

其中有兩個(gè)重要組成部分,QUIC SLB和QUIC Server:

  • QUIC SLB工作在傳輸層,具有負(fù)載均衡能力,負(fù)責(zé)接收并正確轉(zhuǎn)發(fā)UDP數(shù)據(jù)包至Server。當(dāng)用戶進(jìn)行網(wǎng)絡(luò)切換,導(dǎo)致連接四元組發(fā)生變化時(shí),SLB通過從連接CID中提取Server端的ip+port來實(shí)現(xiàn)數(shù)據(jù)包的準(zhǔn)確轉(zhuǎn)發(fā),從而支持連接遷移功能;
  • QUIC Server工作在應(yīng)用層,是QUIC協(xié)議的主要實(shí)現(xiàn)所在,負(fù)責(zé)轉(zhuǎn)發(fā)及響應(yīng)客戶端請(qǐng)求,通過Server集群共享ticket_key方案實(shí)現(xiàn)0-RTT功能;

1.2 QUIC高可用及性能提升

隨著全球旅游業(yè)的復(fù)蘇,攜程在國(guó)內(nèi)外的業(yè)務(wù)迎來了成倍的增長(zhǎng),業(yè)務(wù)體量越來越龐大,QUIC作為Trip.com APP的主要網(wǎng)絡(luò)通道,其重要性不言而喻。為了更好地應(yīng)對(duì)日益增長(zhǎng)的流量,更穩(wěn)定地支持每一次用戶請(qǐng)求的送達(dá),我們建立了QUIC高可用及性能提升的目標(biāo),最終完成了以下優(yōu)化內(nèi)容:

QUIC集群及鏈路高可用優(yōu)化:

  • 完成QUIC Server容器化改造,具備了HPA能力,并定制化開發(fā)了適用于QUIC場(chǎng)景的HPA指標(biāo)
  • 優(yōu)化QUIC網(wǎng)絡(luò)架構(gòu),具備了QUIC Server的主動(dòng)健康監(jiān)測(cè)及動(dòng)態(tài)上下線能力
  • 通過推拉結(jié)合的策略,有效提升了客戶端App容災(zāi)能力,實(shí)現(xiàn)網(wǎng)絡(luò)通道和入口ip秒級(jí)切換
  • 搭建了穩(wěn)定可靠的監(jiān)控告警體系

QUIC成功率及鏈路性能提升:

  • 支持QUIC全鏈路埋點(diǎn),使QUIC運(yùn)行時(shí)數(shù)據(jù)更加透明化
  • 通過優(yōu)化擁塞控制算法實(shí)現(xiàn)了鏈路性能的進(jìn)一步提升
  • 通過多Region部署縮短了歐洲用戶20%的鏈路耗時(shí)
  • 客戶端Cronet升級(jí),網(wǎng)絡(luò)請(qǐng)求速度提升明顯

QUIC應(yīng)用場(chǎng)景拓展:

  • 支持?jǐn)y程旅行App和商旅海外App接入QUIC,國(guó)內(nèi)用戶和商旅用戶在海外場(chǎng)景下網(wǎng)絡(luò)成功率和性能大幅提升

下文將詳細(xì)的介紹這些優(yōu)化內(nèi)容。

二、QUIC網(wǎng)絡(luò)架構(gòu)升級(jí)

2.1 容器化改造

改造前我們統(tǒng)一使用VM部署QUIC SLB和QUIC Server,具體部署流程如下:

圖片

QUIC實(shí)踐早期我們經(jīng)常需要在機(jī)器上執(zhí)行自定義操作,這種部署方案的優(yōu)點(diǎn)是比較靈活。但隨著QUIC服務(wù)端功能趨于穩(wěn)定,以及業(yè)務(wù)流量的日益增長(zhǎng),此方案部署時(shí)間長(zhǎng)、不支持動(dòng)態(tài)擴(kuò)縮容的弊端日益顯現(xiàn)。為了解決以上問題,我們對(duì)QUIC SLB以及QUIC Server進(jìn)行了容器化改造:

  • QUIC Server承載了QUIC協(xié)議處理以及用戶http請(qǐng)求轉(zhuǎn)發(fā)這兩項(xiàng)核心功能,我們將其改造成了容器鏡像,并接入到內(nèi)部Captain發(fā)布系統(tǒng)中,支持了灰度發(fā)布,版本回退等功能,降低了發(fā)布帶來的風(fēng)險(xiǎn),同時(shí)具備了HPA能力,擴(kuò)縮容時(shí)間由分鐘級(jí)縮短到秒級(jí)

圖片

  • QUIC SLB作為外網(wǎng)入口,主要負(fù)責(zé)用戶UDP包的轉(zhuǎn)發(fā),負(fù)載較小,對(duì)流量變化不敏感。并且由于需要Akamai加速,QUIC SLB需要同時(shí)支持UDP以及TCP協(xié)議,當(dāng)前容器是無法支持雙協(xié)議的外網(wǎng)入口的。因此我們將QUIC SLB改造成了虛擬機(jī)鏡像,支持在PaaS上一鍵擴(kuò)容,大大降低了部署成本

圖片

2.2 服務(wù)發(fā)現(xiàn)與主動(dòng)健康監(jiān)測(cè)

在QUIC SLB中,我們使用Nginx作為4層代理,實(shí)現(xiàn)QUIC UDP數(shù)據(jù)包的轉(zhuǎn)發(fā)以及連接遷移能力。

容器化后的前期我們使用Consul作為QUIC Server的注冊(cè)中心,Server會(huì)在k8s提供的生命周期函數(shù)postStart和preStop中分別調(diào)用Consul的注冊(cè)和刪除API,將自身ip在Consul中注冊(cè)或摘除。QUIC SLB會(huì)監(jiān)聽Consul中ip的變化,從而及時(shí)感知到每個(gè)Quic Server的狀態(tài),并實(shí)時(shí)更新到Nginx的配置文件中,這樣就實(shí)現(xiàn)了QUIC Server的自動(dòng)注冊(cè)與發(fā)現(xiàn)。

但在實(shí)際演練場(chǎng)景中,我們發(fā)現(xiàn)當(dāng)直接對(duì)QUIC Server注入故障時(shí),由于Server所在pod并沒有被銷毀,因此不會(huì)觸發(fā)preStop API的調(diào)用,故障Server無法在Consul中摘除自身ip,導(dǎo)致QUIC SLB無法感知到Server的下線,因此QUIC SLB的nginx.conf中依舊會(huì)保留故障的Server ip,這種情況在Nginx做TCP代理和UDP代理時(shí)所產(chǎn)生的影響不同:

  • 當(dāng)Nginx做TCP代理時(shí),Nginx與故障Server之間建立的是TCP連接,Server故障時(shí)TCP連接會(huì)斷開,Nginx會(huì)與故障Server重新建聯(lián)但最終失敗,此時(shí)會(huì)自動(dòng)將其拉出一段時(shí)間,并每隔一段時(shí)間進(jìn)行探測(cè),直至其恢復(fù),從而避免了TCP數(shù)據(jù)包轉(zhuǎn)發(fā)至錯(cuò)誤的Server,不會(huì)導(dǎo)致服務(wù)成功率下降;
  • 當(dāng)Nginx做UDP代理時(shí),由于UDP是無連接的,QUIC SLB依舊會(huì)轉(zhuǎn)發(fā)數(shù)據(jù)包至故障Server,但SLB不會(huì)收到任何響應(yīng)數(shù)據(jù)包,由于UDP協(xié)議特性,此時(shí)QUIC SLB不會(huì)判定Server為異常,從而持續(xù)大量的UDP包被轉(zhuǎn)發(fā)到故障Server實(shí)例上,導(dǎo)致QUIC通道的成功率大幅下降;

圖片

經(jīng)過上述分析,我們知道了使用UDP進(jìn)行健康監(jiān)測(cè)存在一定弊端,期望使用TCP協(xié)議對(duì)QUIC Server進(jìn)行主動(dòng)的健康檢測(cè)。所以開啟了新方案的探索,其需要同時(shí)支持UDP數(shù)據(jù)轉(zhuǎn)發(fā),基于TCP協(xié)議的主動(dòng)健康監(jiān)測(cè),支持服務(wù)發(fā)現(xiàn)與注冊(cè),并且能夠較好的適配QUIC SLB層。

調(diào)研了很多方案,其中較適配的是開源的Nginx UDP Health Check項(xiàng)目,其同時(shí)支持UDP數(shù)據(jù)包轉(zhuǎn)發(fā)和TCP的主動(dòng)健康檢測(cè),但是其不支持nginx.conf中下游ip的動(dòng)態(tài)變更,也就是不支持QUIC Server的動(dòng)態(tài)上下線,這直接影響了Server集群的HPA能力,因此舍棄了這個(gè)方案。

最終通過調(diào)研發(fā)現(xiàn)公司內(nèi)部的L4LB組件,既能同時(shí)支持TCP的主動(dòng)健康檢測(cè)和UDP數(shù)據(jù)包轉(zhuǎn)發(fā),還支持實(shí)例的動(dòng)態(tài)上下線,完美適配我們的場(chǎng)景,因此最終采用了L4LB作為QUIC SLB和QUIC Server之間的轉(zhuǎn)發(fā)樞紐。

圖片

具體實(shí)現(xiàn)是為QUIC Server的每個(gè)group申請(qǐng)一個(gè)UDP的內(nèi)網(wǎng)L4LB入口ip,這些ip是固定不變的,那么對(duì)于QUIC SLB來說只需要將UDP數(shù)據(jù)包轉(zhuǎn)發(fā)至固定的虛擬ip即可。L4LB開啟TCP的健康檢測(cè)功能,這樣當(dāng)group中的QUIC Server實(shí)例故障時(shí),健康檢測(cè)失敗,L4LB就會(huì)將此實(shí)例拉出,后續(xù)UDP包就不會(huì)再轉(zhuǎn)發(fā)到此實(shí)例上,直至實(shí)例再次恢復(fù)到健康狀態(tài)。這樣就完美解決了QUIC Server的自動(dòng)注冊(cè)與主動(dòng)健康監(jiān)測(cè)功能。

圖片

2.3 推拉結(jié)合方式提升客戶端用戶側(cè)網(wǎng)絡(luò)容災(zāi)能力

Trip.com App的網(wǎng)絡(luò)請(qǐng)求框架同時(shí)支持QUIC/TCP/HTTP 三通道能力,其中80%以上的用戶請(qǐng)求都是通過QUIC通道訪問服務(wù)器的,日均流量達(dá)到數(shù)億,在現(xiàn)有的多通道/多IP切換能力的基礎(chǔ)上,進(jìn)一步提升容災(zāi)能力顯得尤為重要。于是我們?cè)O(shè)計(jì)了一套推拉結(jié)合的策略方案,結(jié)合公司配置系統(tǒng)實(shí)現(xiàn)了秒級(jí)通道/IP切換。下面是簡(jiǎn)化過程:

在客戶端App啟動(dòng)和前后臺(tái)切換等場(chǎng)景,根據(jù)變動(dòng)情況獲取最新的配置,網(wǎng)絡(luò)框架基于最新的配置進(jìn)行無損通道或IP的切換。

圖片

同時(shí)當(dāng)用戶APP處于前臺(tái)活躍狀態(tài)時(shí),通過對(duì)用戶進(jìn)行主動(dòng)的配置更新推送,讓在線用戶可以立即感知到變化并切換至最新的網(wǎng)絡(luò)配置上面,且此切換過程對(duì)用戶是無感的。

圖片

這樣一來,我們的QUIC客戶端網(wǎng)絡(luò)框架進(jìn)一步提升了容災(zāi)能力,當(dāng)某個(gè)IP發(fā)生故障時(shí),可以在秒級(jí)通知所有用戶切離故障IP,當(dāng)某通道發(fā)生異常時(shí),用戶亦可以無感的切換至優(yōu)質(zhì)通道,而不會(huì)受到任何影響。

2.4 監(jiān)控告警穩(wěn)定性保證及彈性擴(kuò)縮容指標(biāo)建設(shè)

QUIC數(shù)據(jù)監(jiān)控系統(tǒng)的穩(wěn)定性,對(duì)于故障預(yù)警、故障響應(yīng)起到至關(guān)重要的作用。通過將埋點(diǎn)數(shù)據(jù)寫至access log和error log來完成QUIC運(yùn)行時(shí)埋點(diǎn)數(shù)據(jù)的輸出,再通過logagent將服務(wù)器本地的日志數(shù)據(jù)發(fā)送至Kafka,隨后Hangout消費(fèi)并解析,將數(shù)據(jù)落入Clickhouse做數(shù)據(jù)存儲(chǔ)及查詢,這給我們做運(yùn)行時(shí)數(shù)據(jù)觀察及數(shù)據(jù)分析提供了很大的便利性。

圖片

在完成QUIC網(wǎng)絡(luò)架構(gòu)升級(jí)之后,只依靠上述日志體系遇到了下面兩類問題:

第一,在應(yīng)用場(chǎng)景下,單純依靠這部分?jǐn)?shù)據(jù)做監(jiān)控告警,偶發(fā)由于某些中間環(huán)節(jié)出現(xiàn)波動(dòng)導(dǎo)致監(jiān)控告警不準(zhǔn)確, 例如Hangout消費(fèi)者故障導(dǎo)致流量驟降或突增的假象,這可能會(huì)影響監(jiān)控告警的及時(shí)性和準(zhǔn)確性;

第二,容器化之后具備了彈性擴(kuò)縮容能力,而HPA依賴于擴(kuò)縮容數(shù)據(jù)指標(biāo),僅僅使用CPU、內(nèi)存利用率等資源指標(biāo),無法充足的反映QUIC服務(wù)器狀態(tài)。根據(jù)QUIC服務(wù)特性,仍需要自定義一些HPA數(shù)據(jù)指標(biāo),例如空閑連接占比,空閑端口號(hào)占比等,以建立更合理、更穩(wěn)定的擴(kuò)縮容依賴;

基于上述兩方面的考量,在經(jīng)過調(diào)研之后,我們將Nginx與Prometheus進(jìn)行整合,支持了關(guān)鍵數(shù)據(jù)指標(biāo)、擴(kuò)縮容數(shù)據(jù)指標(biāo)通過Prometheus上報(bào)的方案。在Nginx中預(yù)先對(duì)成功率,耗時(shí),可用連接數(shù)等等重要指標(biāo)進(jìn)行了聚合,只上報(bào)聚合數(shù)據(jù)指標(biāo),從而大大縮小了數(shù)據(jù)體量,使Nginx整合Prometheus的影響可以忽略不計(jì)。另外我們支持了空閑連接占比,空閑端口號(hào)占比等等HPA指標(biāo),使QUIC集群在流量高峰期,能夠非常準(zhǔn)確迅速的完成系統(tǒng)擴(kuò)容,在低流量時(shí)間段,也能夠縮容至適配狀態(tài),以最大程度的節(jié)約機(jī)器資源。

圖片

這樣一來,QUIC系統(tǒng)的監(jiān)控告警數(shù)據(jù)來源同時(shí)支持Prometheus和Clickhouse,Prometheus側(cè)重關(guān)鍵指標(biāo)及聚合數(shù)據(jù)的上報(bào),Clickhouse側(cè)重運(yùn)行時(shí)明細(xì)數(shù)據(jù)的上報(bào),兩者相互配合互為補(bǔ)充。

在支持Prometheus過程中我們遇到了較多依賴項(xiàng)的版本搭配導(dǎo)致的編譯問題,以nginx/1.25.3版本為例,給出版本匹配結(jié)果:

組件名

描述

版本

下載鏈接

nginx-quic

nginx官方庫

1.25.3

https://github.com/nginx/nginx/releases/tag/release-1.25.3

nginx-lua-prometheus

lua-prometheus語法庫

0.20230607

https://github.com/knyar/nginx-lua-prometheus/releases/tag/0.20230607

luajit

lua即時(shí)編譯

v2.1-20231117

https://github.com/openresty/luajit2/releases/tag/v2.1-20231117

lua-nginx-module

lua-nginx框架

v0.10.25

https://github.com/openresty/lua-nginx-module/releases/tag/v0.10.25

ngx_devel_kit

lua-nginx依賴的開發(fā)包

v0.3.3

https://github.com/vision5/ngx_devel_kit/releases/tag/v0.3.3

lua-resty-core

lua-resty核心模塊

v0.1.27

https://github.com/openresty/lua-resty-core/releases/tag/v0.1.27

lua-resty-lrucache

lua-resty lru緩存模塊

v0.13

https://github.com/openresty/lua-resty-lrucache/releases/tag/v0.13

三、全鏈路埋點(diǎn)

3.1 落地實(shí)踐

我們基于優(yōu)化用戶鏈路耗時(shí),尋找并優(yōu)化耗時(shí)短板的目標(biāo)出發(fā),開始抽樣分析耗時(shí)較久的請(qǐng)求,并根據(jù)所需,在服務(wù)端access.log中逐漸添加了較多的數(shù)據(jù)埋點(diǎn),nginx官方對(duì)單個(gè)http請(qǐng)求維度的數(shù)據(jù)埋點(diǎn)支持性較好,但僅僅分析單個(gè)請(qǐng)求維度的信息,難以看清請(qǐng)求所屬連接的各類數(shù)據(jù),仍需要觀察用戶連接所處網(wǎng)絡(luò)環(huán)境,握手細(xì)節(jié),數(shù)據(jù)傳輸細(xì)節(jié),擁塞情況等等數(shù)據(jù),來協(xié)助對(duì)問題進(jìn)行定位。

QUIC客戶端之前僅有端到端的整體埋點(diǎn)數(shù)據(jù),并且存在QUIC埋點(diǎn)體系和現(xiàn)有體系mapping的問題,我們收集過濾Cronet metrics的信息,整合進(jìn)現(xiàn)有埋點(diǎn)體系內(nèi)。

3.1.1 收集過濾QUIC客戶端Cronet Metrics埋點(diǎn)數(shù)據(jù)

端到端流程支持了DNS、TLS握手、請(qǐng)求發(fā)送、響應(yīng)返回等環(huán)節(jié)細(xì)粒度的埋點(diǎn),QUIC端到端各環(huán)節(jié)數(shù)據(jù)一目了然。

圖片

3.1.2 改造服務(wù)端nginx源碼

我們?cè)谶B接創(chuàng)建到連接銷毀的全生命周期內(nèi)進(jìn)行了詳細(xì)的數(shù)據(jù)埋點(diǎn),另外通過連接CID實(shí)現(xiàn)了連接級(jí)別埋點(diǎn)和請(qǐng)求級(jí)別埋點(diǎn)數(shù)據(jù)的串聯(lián),這對(duì)進(jìn)行問題定位,性能優(yōu)化等提供了可靠的數(shù)據(jù)支持。下面分類列舉了部分服務(wù)端全鏈路埋點(diǎn),并簡(jiǎn)要概述了其用途:

1)連接生命周期時(shí)間線

連接類型(1-rtt/0-rtt),連接創(chuàng)建時(shí)間(Server收到Client第一個(gè)數(shù)據(jù)包的時(shí)間),連接發(fā)送第一個(gè)數(shù)據(jù)包的時(shí)間,連接收到第一個(gè)ack幀的時(shí)間,連接握手耗時(shí),連接收到及發(fā)送cc幀(Connection Close Frame)的時(shí)間,連接無響應(yīng)超時(shí)時(shí)間,連接銷毀時(shí)間等等;這一類埋點(diǎn)主要幫助我們理清用戶連接生命周期中的各個(gè)關(guān)鍵時(shí)間點(diǎn),以及握手相關(guān)的耗時(shí)細(xì)節(jié)。

2)數(shù)據(jù)傳輸細(xì)節(jié)

(以下皆為連接生命周期內(nèi))發(fā)送和接收字節(jié)、數(shù)據(jù)包、數(shù)據(jù)幀總數(shù),包重傳率,幀重傳率等等。這類數(shù)據(jù)幫助分析我們的數(shù)據(jù)傳輸特性,對(duì)鏈路傳輸優(yōu)化,擁塞控制算法調(diào)整提供數(shù)據(jù)參考。

3)RTT(Round-trip time)和擁塞控制數(shù)據(jù)

平滑RTT,最小RTT,首次和最后一次RTT,擁塞窗口大小,最大in_flight,慢開始閾值,擁塞recovery_start時(shí)間等等。這些數(shù)據(jù)可用來分析用戶網(wǎng)絡(luò)狀況,觀察擁塞比例,評(píng)估擁塞控制算法合理性等等。

4)用戶信息

客戶端ip,國(guó)家及地區(qū)等。這幫助我們對(duì)用戶數(shù)據(jù)進(jìn)行區(qū)域級(jí)別的聚合分析,找到網(wǎng)絡(luò)傳輸?shù)膮^(qū)域性差異,以進(jìn)行一些針對(duì)性優(yōu)化。

3.2 分析挖掘

通過合并聚合各類數(shù)據(jù)埋點(diǎn),實(shí)現(xiàn)了QUIC運(yùn)行時(shí)數(shù)據(jù)可視化透明化,這也幫助我們發(fā)現(xiàn)了諸多問題及優(yōu)化項(xiàng),下面列舉幾項(xiàng)進(jìn)行詳述:

3.2.1 0-rtt連接存活時(shí)間異常,導(dǎo)致重復(fù)請(qǐng)求問題

通過篩選0-rtt類型的連接,我們觀察到此類連接的存活總時(shí)間,恰好等于QUIC客戶端和服務(wù)端協(xié)商之后的max_idel_timeout,而max_idel_timeout的準(zhǔn)確定義為”連接無響應(yīng)(客戶端服務(wù)端無任何數(shù)據(jù)交互)超時(shí)關(guān)閉時(shí)間“,也就是說正常情況下,當(dāng)一個(gè)連接上最后一次http請(qǐng)求交互完畢之后,若經(jīng)過max_idel_timeout時(shí)間仍未發(fā)生其他交互時(shí),連接會(huì)進(jìn)入關(guān)閉流程;當(dāng)連接上不斷的有請(qǐng)求交互時(shí),連接的存活時(shí)間必定大于max_idel_timeout(實(shí)際連接存活時(shí)間 = 最后一次請(qǐng)求數(shù)據(jù)傳輸完成時(shí)間 - 連接創(chuàng)建時(shí)間 + max_idel_timeout)。

為了論證上述現(xiàn)象,我們通過連接的dcid,關(guān)聯(lián)篩選出0-rtt連接生命周期中所有http請(qǐng)求列表,發(fā)現(xiàn)即使連接上的請(qǐng)求在不斷的進(jìn)行,0-rtt連接仍然會(huì)在存活了max_idel_timeout時(shí)無條件關(guān)閉,所以斷定0-rtt連接的續(xù)命邏輯存在問題。我們對(duì)nginx-quic源碼進(jìn)行閱讀分析,最終定位并及時(shí)修復(fù)了問題代碼:

圖片

在源碼ngx_quic_run()函數(shù)中,存在兩個(gè)連接相關(guān)的定時(shí)器:

圖片

兩者都會(huì)影響連接的關(guān)閉,其中c->read定時(shí)器存在續(xù)命邏輯,會(huì)隨著連接生命周期內(nèi),請(qǐng)求的不斷發(fā)生而刷新定時(shí)器。qc->close在源碼中不存在續(xù)命邏輯,有且僅有一處刪除邏輯,即在執(zhí)行ngx_quic_handle_datagram()函數(shù)過程中,若完成了ssl初始化,則調(diào)用ngx_quic_do_init_streams()進(jìn)行qc->close定時(shí)器的刪除操作;

  • 若為1-rtt建聯(lián),第一次執(zhí)行ngx_quic_handle_datagram()函數(shù)不會(huì)完成ssl初始化,所以qc->close的創(chuàng)建發(fā)生在ssl初始化完畢之前,在后續(xù)數(shù)據(jù)包交互過程中能夠正常完成刪除邏輯;
  • 若為0-rtt建聯(lián),第一次執(zhí)行ngx_quic_handle_datagram()函數(shù)會(huì)完成ssl初始化邏輯,所以僅一次的刪除邏輯,發(fā)生在了qc->close定時(shí)器設(shè)置之前,所以導(dǎo)致qc->close不能被正常移除,從而導(dǎo)致max_idel_timeout時(shí)間一到,連接立即關(guān)閉的現(xiàn)象;

這個(gè)bug除了導(dǎo)致較多無效0-rtt新建連之外,在我們的應(yīng)用場(chǎng)景下,經(jīng)過對(duì)全鏈路埋點(diǎn)數(shù)據(jù)聚合分析發(fā)現(xiàn),還會(huì)導(dǎo)致重復(fù)請(qǐng)求問題,下面介紹發(fā)生重復(fù)請(qǐng)求的原因:

圖片

quic client發(fā)起某個(gè)request的第一次請(qǐng)求,quic server端收到并轉(zhuǎn)發(fā)給后端應(yīng)用,在server收到后端應(yīng)用response之前,恰好qc->close定時(shí)器到期,導(dǎo)致server立即向client發(fā)送cc幀,client在收到cc幀后,按照quic協(xié)議應(yīng)無條件立即關(guān)閉當(dāng)前連接,所以client認(rèn)為第一次請(qǐng)求失敗,從而發(fā)起新建連,開始第二次請(qǐng)求,從而導(dǎo)致重復(fù)請(qǐng)求問題。而這個(gè)過程從客戶端業(yè)務(wù)角度來說只請(qǐng)求了一次,但后端應(yīng)用卻連續(xù)收到兩次一模一樣的請(qǐng)求,這對(duì)于冪等性要求較高的接口影響較大。

我們?cè)?024年2月發(fā)現(xiàn)并修復(fù)了上述定時(shí)器bug,修復(fù)之后連接復(fù)用比例提升0.5%,不必要的0-rtt建連比例降低7%。目前nginx-quic官方分支于2024/04/10也提交了對(duì)此問題的修復(fù),Commit鏈接:https://hg.nginx.org/nginx-quic/rev/155c9093de9d

3.2.2 客戶端App Cronet升級(jí)給95線用戶帶來體驗(yàn)提升

經(jīng)過數(shù)據(jù)分析發(fā)現(xiàn),長(zhǎng)尾用戶在0-RTT上占比不高,大多為1-RTT新建連接,經(jīng)過分析判斷可能和QUIC客戶端Cronet裁剪有關(guān)。Trip.com App上Cronet庫在優(yōu)化前使用的是2020年的舊版本,并且由于包大小問題對(duì)其進(jìn)行了裁剪(比如:重構(gòu)了PSK相關(guān)邏輯,轉(zhuǎn)為session級(jí)別),在保留關(guān)鍵功能的前提下盡可能剔除了無用代碼十幾萬行。同時(shí)經(jīng)過與其他Cronet使用方溝通,得到Cronet升級(jí)后有不錯(cuò)的性能提升表現(xiàn),于是時(shí)隔近四年,客戶端對(duì)Cronet庫進(jìn)行了一次大升級(jí)。

另外,由于Chromium官方在2023年11月份官宣不再提供iOS的Cli工具,所以此次升級(jí)目標(biāo)就定位選一個(gè)盡可能靠近官方刪除iOS構(gòu)建工具之前的版本,最終我們選定了 120.0.6099.301。

圖片

經(jīng)過Cronet升級(jí)及相關(guān)適配性改造,對(duì)線上升級(jí)前后版本進(jìn)行對(duì)比,升級(jí)后用戶側(cè)95線請(qǐng)求耗時(shí)降低了18%。

3.2.3 Nginx-quic分支中擁塞控制算法實(shí)現(xiàn)具有較大的優(yōu)化空間

通過對(duì)nginx-quic源碼的研究以及鏈路埋點(diǎn)的數(shù)據(jù)分析,我們發(fā)現(xiàn)源碼中的擁塞控制算法為Reno算法的簡(jiǎn)化版,初始傳輸窗口設(shè)置較大為131054字節(jié)(若mtu為1200,初始就有109個(gè)包可以同時(shí)傳輸)。若發(fā)生擁塞事件,降窗的最小值仍為131054字節(jié),在網(wǎng)絡(luò)較好時(shí),網(wǎng)絡(luò)公平性不友好,在網(wǎng)絡(luò)較差時(shí),這會(huì)加劇網(wǎng)絡(luò)擁堵。在發(fā)現(xiàn)此問題后,我們開始著手改造源碼中的擁塞控制算法邏輯,這一優(yōu)化內(nèi)容將在第四部分詳述。

四、擁塞控制算法探索

nginx-quic官方分支中,對(duì)于擁塞控制算法的實(shí)現(xiàn)目前仍處于demo級(jí)別,我們結(jié)合QUIC在應(yīng)用層實(shí)現(xiàn)擁塞控制算法而不依賴于操作系統(tǒng)的特性,對(duì)Nginx官方代碼中擁塞控制相關(guān)邏輯進(jìn)行了抽象重構(gòu),以方便拓展各種算法,并支持了可配置式的擁塞控制算法切換,可以根據(jù)不同的網(wǎng)絡(luò)狀況,不同的server業(yè)務(wù)場(chǎng)景配置不同的擁塞控制算法。

4.1 擁塞控制算法簡(jiǎn)介

目前主流的擁塞控制算法大抵可分為兩類,一類是根據(jù)丟包做響應(yīng),如Reno、Cubic,一類是根據(jù)帶寬和延遲反饋?zhàn)鲰憫?yīng),如BBR系列。這里簡(jiǎn)要介紹下Reno,Cubic和BBR的工作原理,適用場(chǎng)景及優(yōu)缺點(diǎn):

1)Reno算法是TCP最早的擁塞控制算法之一,基于丟包的擁塞控制機(jī)制。它使用兩個(gè)閾值(慢啟動(dòng)閾值和擁塞避免閾值)來控制發(fā)送速率。在慢啟動(dòng)階段,發(fā)送方每經(jīng)過一個(gè)往返時(shí)間(RTT),就將擁塞窗口大小加倍。一旦出現(xiàn)擁塞,會(huì)觸發(fā)擁塞避免階段,發(fā)送速率會(huì)緩慢增長(zhǎng)。當(dāng)發(fā)生丟包時(shí),發(fā)送方會(huì)認(rèn)為發(fā)生了擁塞,將擁塞窗口大小減半;適用于低延時(shí)、低帶寬的場(chǎng)景,對(duì)于早期互聯(lián)網(wǎng)環(huán)境比較適用。其優(yōu)點(diǎn)是簡(jiǎn)單直觀,易于理解和實(shí)現(xiàn)。缺點(diǎn)是對(duì)網(wǎng)絡(luò)變化反應(yīng)較慢,可能導(dǎo)致網(wǎng)絡(luò)利用率不高,且在丟包率較高時(shí)性能不佳。

2)Cubic算法在Reno算法的基礎(chǔ)上進(jìn)行改進(jìn),利用網(wǎng)絡(luò)往返時(shí)間(RTT)和擁塞窗口的變化率來計(jì)算擁塞窗口的大小,使用擬立方函數(shù)來模擬網(wǎng)絡(luò)的擁塞狀態(tài),并根據(jù)擁塞窗口的大小和時(shí)間來調(diào)整擁塞窗口的增長(zhǎng)速率。適用于中度丟包率的網(wǎng)絡(luò)環(huán)境,對(duì)于互聯(lián)網(wǎng)主流環(huán)境有較好的性能表現(xiàn)。優(yōu)點(diǎn)是相對(duì)于Reno算法,能更好地適應(yīng)網(wǎng)絡(luò)變化,提高網(wǎng)絡(luò)利用率。缺點(diǎn)是在高丟包率或長(zhǎng)肥管道環(huán)境下,發(fā)送窗口可能會(huì)迅速收斂到很小,導(dǎo)致性能下降。

3)BBR(Bottleneck Bandwidth and RTT)算法是Google開發(fā)的一種擁塞控制算法,通過測(cè)量網(wǎng)絡(luò)的帶寬和往返時(shí)間來估計(jì)網(wǎng)絡(luò)的擁塞程度,并根據(jù)擁塞程度調(diào)整發(fā)送速率。BBR算法的特點(diǎn)是能夠更精確地估計(jì)網(wǎng)絡(luò)的擁塞程度,避免了過度擁塞和欠擁塞的情況,提高了網(wǎng)絡(luò)的傳輸速度和穩(wěn)定性。適用于高帶寬、高延時(shí)或中度丟包率的網(wǎng)絡(luò)環(huán)境。優(yōu)點(diǎn)是能夠更精確地控制發(fā)送速率,提高網(wǎng)絡(luò)利用率和穩(wěn)定性。缺點(diǎn)是可能占用額外的CPU資源,影響性能,且在某些情況下可能存在公平性問題。

4.2 優(yōu)化實(shí)現(xiàn)及收益

源碼中有關(guān)擁塞控制邏輯的代碼分散在各處功能代碼中,未進(jìn)行抽象統(tǒng)一管理,我們通過梳理擁塞控制算法響應(yīng)事件,將各個(gè)事件函數(shù)抽象如下:

圖片

我們基于上述抽象結(jié)構(gòu),先后實(shí)現(xiàn)了目前主流的擁塞控制算法Reno,Cubic及BBR,并且我們根據(jù)埋點(diǎn)數(shù)據(jù)對(duì)擁塞控制算法進(jìn)行了參數(shù)和邏輯調(diào)優(yōu),包括設(shè)置合理的初始窗口和最小窗口,設(shè)置最優(yōu)的擁塞降窗邏輯等等,這些調(diào)整會(huì)引起包重發(fā)率和連接擁塞率的數(shù)據(jù)變化,而這些數(shù)據(jù)變化皆會(huì)影響到鏈路傳輸性能。

圖片

我們通過對(duì)QUIC擁塞控制算法的優(yōu)化,SHA環(huán)境連接擁塞比例降低了15個(gè)點(diǎn),實(shí)現(xiàn)了SHA端到端耗時(shí)降低4%的收益。后續(xù)將繼續(xù)基于Trip.com的數(shù)據(jù)傳輸特性,根據(jù)每個(gè)IDC的不同網(wǎng)絡(luò)狀況進(jìn)行適應(yīng)性定制化開發(fā),并通過長(zhǎng)期的AB實(shí)驗(yàn),探索每個(gè)IDC下最優(yōu)的擁塞控制邏輯。

五、成果與展望

我們不斷的優(yōu)化QUIC鏈路性能,不斷的提升QUIC通道穩(wěn)定性,旨在為Trip.com日益增長(zhǎng)的業(yè)務(wù)提供優(yōu)質(zhì)的網(wǎng)絡(luò)服務(wù),同時(shí)我們也在不斷的探索支持更多的QUIC應(yīng)用場(chǎng)景。

1)通過容器化改造,將擴(kuò)縮容由手動(dòng)改為自動(dòng),擴(kuò)縮容時(shí)間縮短30倍,在20s內(nèi)就能拉起并上線大批服務(wù)器;

2)通過開發(fā)全鏈路埋點(diǎn),聚合分析出了較多優(yōu)化項(xiàng),修復(fù)0-rtt連接問題,連接復(fù)用比例提升0.5%,優(yōu)化擁塞控制算法,端到端耗時(shí)縮短4%;

3)通過在FRA(法蘭克福)部署QUIC集群,降低了歐洲用戶耗時(shí)20%以上,提高了網(wǎng)絡(luò)成功率0.5%以上;

4)支持了攜程旅行App和商旅海外App接入QUIC,國(guó)內(nèi)用戶和商旅用戶在海外場(chǎng)景下網(wǎng)絡(luò)成功率和性能也大幅提升;

5)客戶端升級(jí)Cronet之后,綜合上述優(yōu)化項(xiàng),用戶側(cè)端到端整體耗時(shí)95線降低18%;

Trip.com在QUIC上的探索將持續(xù)的進(jìn)行,我們將密切關(guān)注社區(qū)動(dòng)態(tài),探索支持更多的QUIC應(yīng)用場(chǎng)景,挖掘更多的優(yōu)化項(xiàng)目,為攜程國(guó)際化戰(zhàn)略貢獻(xiàn)力量。

責(zé)任編輯:張燕妮 來源: 攜程技術(shù)
相關(guān)推薦

2022-04-14 18:01:24

QUICTrip.com服務(wù)端

2021-10-18 12:01:17

iOS自動(dòng)化測(cè)試Trip

2021-05-24 09:28:41

軟件開發(fā) 技術(shù)

2019-10-17 09:05:21

MySQL數(shù)據(jù)庫高可用

2013-10-28 01:44:56

mysql載均衡高可用環(huán)境

2017-09-22 10:05:48

Redis備份容災(zāi)

2017-12-22 09:21:02

API架構(gòu)實(shí)踐

2020-07-29 08:30:48

微服務(wù)架構(gòu)數(shù)據(jù)

2014-11-04 09:26:11

2019-10-11 10:52:42

Web架構(gòu)MongoDB

2022-06-02 12:56:25

容器網(wǎng)絡(luò)云原生

2017-11-27 09:14:29

2025-02-26 03:00:00

2022-05-17 15:51:32

數(shù)據(jù)中心運(yùn)維能力基礎(chǔ)設(shè)施

2015-04-27 11:09:53

GoogleQUIC互聯(lián)網(wǎng)協(xié)議

2019-10-16 10:34:33

數(shù)據(jù)庫大數(shù)據(jù)腳本語言

2020-12-09 09:21:41

微服務(wù)架構(gòu)數(shù)據(jù)

2017-07-10 17:25:40

開發(fā)單號(hào)高可用

2010-04-26 09:06:03

JavaFX 1.3

2018-09-11 09:33:49

Redis高可用架構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)