![]()
作者 | Gianmarco Nalin
譯者 | 平川
最近,Cloudflare 分享 了他們?nèi)绾伟l(fā)現(xiàn)其 CUBIC(一種擁塞控制算法)的 Rust 實(shí)現(xiàn)中存在的一個(gè)問(wèn)題。如果連接初始階段出現(xiàn)了嚴(yán)重的數(shù)據(jù)包丟失,那么該問(wèn)題會(huì)導(dǎo)致這個(gè)算法無(wú)法恢復(fù)。
該問(wèn)題影響了他們的開(kāi)源 Quick UDP Internet Connections(QUIC)實(shí)現(xiàn)庫(kù) quiche。這個(gè)庫(kù)位于其所處理的大部分流量的關(guān)鍵路徑上。團(tuán)隊(duì)將該問(wèn)題追溯到了 Linux 內(nèi)核中一項(xiàng)修復(fù) TCP 問(wèn)題的變更。
Cloudflare 系統(tǒng)工程師 Esteban Carisimo 和首席系統(tǒng)工程師 Antonio Vicente 解釋說(shuō),他們的調(diào)查源于一份關(guān)于入站代理集成測(cè)試管道中出現(xiàn)意外故障的報(bào)告。所有失敗的測(cè)試都有一個(gè)共同點(diǎn):它們都是在連接初始階段丟包率極高的場(chǎng)景下對(duì) CUBIC 進(jìn)行評(píng)估。
正如作者所解釋的那樣,CUBIC 及其他基于丟包率的算法基于一個(gè)基本的前提:
(1) 如果沒(méi)有數(shù)據(jù)包丟失,則提高發(fā)送速率(即提高帶寬利用率); (2) 如果發(fā)生數(shù)據(jù)包丟失,那么基于丟包率的算法就會(huì)認(rèn)為已經(jīng)超過(guò)網(wǎng)絡(luò)容量,發(fā)送方必須進(jìn)行退避(即降低帶寬利用率)。
為了更好地理解這個(gè)問(wèn)題,該團(tuán)隊(duì)構(gòu)建了一個(gè)模擬環(huán)境:在本地主機(jī)上運(yùn)行 Quiche HTTP/3 客戶端和服務(wù)器,采用 CUBIC 作為擁塞控制器,并將往返時(shí)間(RTT)配置為 10 毫秒。客戶端通過(guò) HTTP/3 下載了一個(gè) 10MB 大小的文件,并在前兩秒內(nèi)注入了 30% 的隨機(jī)數(shù)據(jù)包丟失。根據(jù)估計(jì),該測(cè)試將在大約四到五秒內(nèi)完成,因此 10 秒的超時(shí)時(shí)間似乎相當(dāng)寬裕。
模擬測(cè)試的結(jié)果證實(shí)了在失敗的集成測(cè)試管道中觀察到的情況:在多次各執(zhí)行 100 次的測(cè)試中,約有 60% 的測(cè)試未能在 10 秒超時(shí)前完成。
該團(tuán)隊(duì)在其實(shí)現(xiàn)中加入了監(jiān)控機(jī)制,用于收集有關(guān)故障行為的詳細(xì)信息。他們注意到,在數(shù)據(jù)包丟失之后,擁塞窗口并沒(méi)有像預(yù)期的那樣擴(kuò)大,也沒(méi)有顯示出任何恢復(fù)跡象。此外,監(jiān)控?cái)?shù)據(jù)顯示,在沒(méi)有數(shù)據(jù)包丟失的階段,CUBIC 在“擁塞規(guī)避狀態(tài)”和“恢復(fù)狀態(tài)”之間進(jìn)行著快速的狀態(tài)轉(zhuǎn)換。具體而言,約 6.7 秒內(nèi)發(fā)生了 999 次狀態(tài)轉(zhuǎn)換:平均每 ~14 毫秒一次。研究團(tuán)隊(duì)認(rèn)為,這一頻率與為連接配置的 10 毫秒 RTT 值過(guò)于接近,令人起疑。
![]()
出現(xiàn)故障時(shí)累計(jì)數(shù)據(jù)包丟失率與擁塞窗口大小的對(duì)比(圖片來(lái)源:Cloudflare 博客)
為了排除一個(gè)更廣泛的問(wèn)題,該團(tuán)隊(duì)還希望用另一種基于損失的擁塞控制算法 Reno 來(lái)取代 CUBIC。模擬的 Reno 測(cè)試 100% 通過(guò),因此,問(wèn)題范圍限定在了 CUBIC 上。
根據(jù)該團(tuán)隊(duì)的說(shuō)法,CUBIC 計(jì)算空閑時(shí)間的方式導(dǎo)致該實(shí)現(xiàn)陷入了一個(gè)無(wú)休止的恢復(fù)循環(huán)。在嘈雜的 慢啟動(dòng) 階段,當(dāng)傳入的 ACK 數(shù)據(jù)包將傳輸中的字節(jié)數(shù)降為零時(shí),該循環(huán)便會(huì)被觸發(fā)。作者指出,當(dāng)最小擁塞窗口為兩個(gè)數(shù)據(jù)包時(shí),空閑期優(yōu)化便會(huì)變成一種“自我實(shí)現(xiàn)的預(yù)言”。該循環(huán)會(huì)將應(yīng)用程序的狀態(tài)維持在恢復(fù)狀態(tài),而且恢復(fù)時(shí)間被設(shè)定在遙遠(yuǎn)的未來(lái),這阻礙了擁塞窗口的擴(kuò)大。
據(jù) Reddit 用戶 RelevantKnowledge485 的描述,其他人也遇到了類似的問(wèn)題:
我們?cè)谔幚硪蕾嚩〞r(shí)器的高頻工作負(fù)載時(shí),也遇到了一個(gè)驚人相似的問(wèn)題,當(dāng)時(shí) C 狀態(tài)的切換導(dǎo)致了不可預(yù)測(cè)的延遲峰值。這里的調(diào)試方法——將內(nèi)核的電源管理決策與協(xié)議層的重傳行為相關(guān)聯(lián)——確實(shí)非常可靠。
作者表示,這一探索最終取得了圓滿的成功,而且與該行為的復(fù)雜性相比,解決方案相當(dāng)簡(jiǎn)單。他們寫(xiě)道:
這是一個(gè)圓滿的結(jié)局:一個(gè)(幾乎)僅需一行代碼的優(yōu)雅的修復(fù)方案,成功打破了這一循環(huán)”。
團(tuán)隊(duì)不再?gòu)纳洗伟l(fā)送數(shù)據(jù)時(shí)開(kāi)始計(jì)算空閑時(shí)間,而是開(kāi)始從收到最后一個(gè) ACK 時(shí)進(jìn)行計(jì)算。
![]()
修復(fù)后的累積數(shù)據(jù)包丟失率與擁塞窗口大小的對(duì)比(圖片來(lái)源:Cloudflare 博客)
這一修復(fù)措施足以打破循環(huán),使擁塞窗口像預(yù)期的那樣恢復(fù),從而使測(cè)試通過(guò)率恢復(fù)到 100%。
https://www.infoq.com/news/2026/06/cloudflare-bug-quiche/
聲明:本文由 InfoQ 翻譯,未經(jīng)許可禁止轉(zhuǎn)載。
![]()
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.