本文經(jīng)原作者授權(quán)轉(zhuǎn)載。
來源知乎
以下為原文
中國科大 LUG 的@高一凡在 LUG HTTP 代理服務(wù)器上部署了 Linux 4.9 的 TCP BBR 擁塞控制算法。從科大的移動出口到新加坡 DigitalOcean 的實測下載速度從 647 KB/s 提高到了 22.1 MB/s(截屏如下)。

此次 Google 提交到 Linux 主線并發(fā)表在 ACM queue 期刊上的 TCP BBR 擁塞控制算法,繼承了 Google “先在生產(chǎn)環(huán)境部署,再開源和發(fā)論文” 的研究傳統(tǒng)。TCP BBR 已經(jīng)在 Youtube 服務(wù)器和 Google 跨數(shù)據(jù)中心的內(nèi)部廣域網(wǎng)(B4)上部署。
TCP BBR 致力于解決兩個問題:
在有一定丟包率的網(wǎng)絡(luò)鏈路上充分利用帶寬。
降低網(wǎng)絡(luò)鏈路上的 buffer 占用率,從而降低延遲。
TCP 擁塞控制的目標(biāo)是最大化利用網(wǎng)絡(luò)上瓶頸鏈路的帶寬。一條網(wǎng)絡(luò)鏈路就像一條水管,要想用滿這條水管,最好的辦法就是給這根水管灌滿水,也就是:
水管內(nèi)的水的數(shù)量 = 水管的容積 = 水管粗細(xì) × 水管長度
換成網(wǎng)絡(luò)的名詞,也就是:
網(wǎng)絡(luò)內(nèi)尚未被確認(rèn)收到的數(shù)據(jù)包數(shù)量 = 網(wǎng)絡(luò)鏈路上能容納的數(shù)據(jù)包數(shù)量 = 鏈路帶寬 × 往返延遲
TCP 維護(hù)一個發(fā)送窗口,估計當(dāng)前網(wǎng)絡(luò)鏈路上能容納的數(shù)據(jù)包數(shù)量,希望在有數(shù)據(jù)可發(fā)的情況下,回來一個確認(rèn)包就發(fā)出一個數(shù)據(jù)包,總是保持發(fā)送窗口那么多個包在網(wǎng)絡(luò)中流動。

TCP 與水管的類比示意(圖片來源:Van Jacobson,Congestion Avoidance and Control,1988)
如何估計水管的容積呢?一種大家都能想到的方法是不斷往里灌水,直到溢出來為止。標(biāo)準(zhǔn) TCP 中的擁塞控制算法也類似:不斷增加發(fā)送窗口,直到發(fā)現(xiàn)開始丟包。這就是所謂的 ”加性增,乘性減”,也就是當(dāng)收到一個確認(rèn)消息的時候慢慢增加發(fā)送窗口,當(dāng)確認(rèn)一個包丟掉的時候較快地減小發(fā)送窗口。
標(biāo)準(zhǔn) TCP 的這種做法有兩個問題:
首先,假定網(wǎng)絡(luò)中的丟包都是由于擁塞導(dǎo)致(網(wǎng)絡(luò)設(shè)備的緩沖區(qū)放不下了,只好丟掉一些數(shù)據(jù)包)。事實上網(wǎng)絡(luò)中有可能存在傳輸錯誤導(dǎo)致的丟包,基于丟包的擁塞控制算法并不能區(qū)分擁塞丟包和錯誤丟包。在數(shù)據(jù)中心內(nèi)部,錯誤丟包率在十萬分之一(1e-5)的量級;在廣域網(wǎng)上,錯誤丟包率一般要高得多。
更重要的是,“加性增,乘性減” 的擁塞控制算法要能正常工作,錯誤丟包率需要與發(fā)送窗口的平方成反比。數(shù)據(jù)中心內(nèi)的延遲一般是 10-100 微秒,帶寬 10-40 Gbps,乘起來得到穩(wěn)定的發(fā)送窗口為 12.5 KB 到 500 KB。而廣域網(wǎng)上的帶寬可能是 100 Mbps,延遲 100 毫秒,乘起來得到穩(wěn)定的發(fā)送窗口為 10 MB。廣域網(wǎng)上的發(fā)送窗口比數(shù)據(jù)中心網(wǎng)絡(luò)高 1-2 個數(shù)量級,錯誤丟包率就需要低 2-4 個數(shù)量級才能正常工作。因此標(biāo)準(zhǔn) TCP 在有一定錯誤丟包率的長肥管道(long-fat pipe,即延遲高、帶寬大的鏈路)上只會收斂到一個很小的發(fā)送窗口。這就是很多時候客戶端和服務(wù)器都有很大帶寬,運營商核心網(wǎng)絡(luò)也沒占滿,但下載速度很慢,甚至下載到一半就沒速度了的一個原因。
其次,網(wǎng)絡(luò)中會有一些 buffer,就像輸液管里中間膨大的部分,用于吸收網(wǎng)絡(luò)中的流量波動。由于標(biāo)準(zhǔn) TCP 是通過 “灌滿水管” 的方式來估算發(fā)送窗口的,在連接的開始階段,buffer 會被傾向于占滿。后續(xù) buffer 的占用會逐漸減少,但是并不會完全消失??蛻舳斯烙嫷乃苋莘e(發(fā)送窗口大小)總是略大于水管中除去膨大部分的容積。這個問題被稱為?bufferbloat(緩沖區(qū)膨脹)。

緩沖區(qū)膨脹現(xiàn)象圖示
緩沖區(qū)膨脹有兩個危害:
增加網(wǎng)絡(luò)延遲。buffer 里面的東西越多,要等的時間就越長嘛。
共享網(wǎng)絡(luò)瓶頸的連接較多時,可能導(dǎo)致緩沖區(qū)被填滿而丟包。很多人把這種丟包認(rèn)為是發(fā)生了網(wǎng)絡(luò)擁塞,實則不然。

往返延遲隨時間的變化。紅線:標(biāo)準(zhǔn) TCP(可見周期性的延遲變化,以及 buffer 幾乎總是被填滿);綠線:TCP BBR
(圖片引自 Google 在 ACM queue 2016 年 9-10 月刊上的論文 [1],下同)
有很多論文提出在網(wǎng)絡(luò)設(shè)備上把當(dāng)前緩沖區(qū)大小的信息反饋給終端,比如在數(shù)據(jù)中心廣泛應(yīng)用的 ECN(Explicit Congestion Notification)。然而廣域網(wǎng)上網(wǎng)絡(luò)設(shè)備眾多,更新?lián)Q代困難,需要網(wǎng)絡(luò)設(shè)備介入的方案很難大范圍部署。
TCP BBR 是怎樣解決以上兩個問題的呢?
既然不容易區(qū)分擁塞丟包和錯誤丟包,TCP BBR 就干脆不考慮丟包。
既然灌滿水管的方式容易造成緩沖區(qū)膨脹,TCP BBR 就分別估計帶寬和延遲,而不是直接估計水管的容積。
帶寬和延遲的乘積就是發(fā)送窗口應(yīng)有的大小。發(fā)明于 2002 年并已進(jìn)入 Linux 內(nèi)核的 TCP Westwood 擁塞控制算法,就是分別估計帶寬和延遲,并計算其乘積作為發(fā)送窗口。然而帶寬和延遲就像粒子的位置和動量,是沒辦法同時測準(zhǔn)的:要測量最大帶寬,就要把水管灌滿,緩沖區(qū)中有一定量的數(shù)據(jù)包,此時延遲就是較高的;要測量最低延遲,就要保證緩沖區(qū)為空,網(wǎng)絡(luò)里的流量越少越好,但此時帶寬就是較低的。
TCP BBR 解決帶寬和延遲無法同時測準(zhǔn)的方法是:交替測量帶寬和延遲;用一段時間內(nèi)的帶寬極大值和延遲極小值作為估計值。
在連接剛建立的時候,TCP BBR 采用類似標(biāo)準(zhǔn) TCP 的慢啟動,指數(shù)增長發(fā)送速率。然而標(biāo)準(zhǔn) TCP 遇到任何一個丟包就會立即進(jìn)入擁塞避免階段,它的本意是填滿水管之后進(jìn)入擁塞避免,然而(1)如果鏈路的錯誤丟包率較高,沒等到水管填滿就放棄了;(2)如果網(wǎng)絡(luò)里有 buffer,總要把緩沖區(qū)填滿了才會放棄。
TCP BBR 則是根據(jù)收到的確認(rèn)包,發(fā)現(xiàn)有效帶寬不再增長時,就進(jìn)入擁塞避免階段。(1)鏈路的錯誤丟包率只要不太高,對 BBR 沒有影響;(2)當(dāng)發(fā)送速率增長到開始占用 buffer 的時候,有效帶寬不再增長,BBR 就及時放棄了(事實上放棄的時候占的是 3 倍帶寬 × 延遲,后面會把多出來的 2 倍 buffer 清掉),這樣就不會把緩沖區(qū)填滿。(應(yīng)評論區(qū)各位 dalao 要求,補充測試環(huán)境說明:是在新加坡的服務(wù)器上設(shè)置了 BBR,新加坡的服務(wù)器是數(shù)據(jù)的發(fā)送方。這個服務(wù)器是訪問墻外資源的 HTTP 代理??拼笠苿映隹诘?DigitalOcean 之間不是 dedicated 的專線,是走的公網(wǎng),科大移動出口這邊是 1 Gbps 無限速(但是要跟其他人 share),DigitalOcean 實測是限速 200 Mbps。RTT 是 66 ms。實測結(jié)果這么好,也是因為大多數(shù)人用的是 TCP Cubic (Linux) / Compound TCP (Windows),在有一定丟包率的情況下,TCP BBR 更加激進(jìn),搶占了更多的公網(wǎng)帶寬。因此也是有些不道德的感覺。)

在慢啟動過程中,由于 buffer 在前期幾乎沒被占用,延遲的最小值就是延遲的初始估計;慢啟動結(jié)束時的最大有效帶寬就是帶寬的初始估計。
慢啟動結(jié)束后,為了把多占用的 2 倍帶寬 × 延遲消耗掉,BBR 將進(jìn)入排空(drain)階段,指數(shù)降低發(fā)送速率,此時 buffer 里的包就被慢慢排空,直到往返延遲不再降低。如下圖綠線所示。

TCP BBR(綠線)與標(biāo)準(zhǔn) TCP(紅線)有效帶寬和往返延遲的比較
排空階段結(jié)束后,BBR 進(jìn)入穩(wěn)定運行狀態(tài),交替探測帶寬和延遲。由于網(wǎng)絡(luò)帶寬的變化比延遲的變化更頻繁,BBR 穩(wěn)定狀態(tài)的絕大多數(shù)時間處于帶寬探測階段。帶寬探測階段是一個正反饋系統(tǒng):定期嘗試增加發(fā)包速率,如果收到確認(rèn)的速率也增加了,就進(jìn)一步增加發(fā)包速率。
具體來說,以每 8 個往返延遲為周期,在第一個往返的時間里,BBR 嘗試增加發(fā)包速率 1/4(即以估計帶寬的 5/4 速度發(fā)送)。在第二個往返的時間里,為了把前一個往返多發(fā)出來的包排空,BBR 在估計帶寬的基礎(chǔ)上降低 1/4 作為發(fā)包速率。剩下 6 個往返的時間里,BBR 使用估計的帶寬發(fā)包。
當(dāng)網(wǎng)絡(luò)帶寬增長一倍的時候,每個周期估計帶寬會增長 1/4,每個周期為 8 個往返延遲。其中向上的尖峰是嘗試增加發(fā)包速率 1/4,向下的尖峰是降低發(fā)包速率 1/4(排空階段),后面 6 個往返延遲,使用更新后的估計帶寬。3 個周期,即 24 個往返延遲后,估計帶寬達(dá)到增長后的網(wǎng)絡(luò)帶寬。

網(wǎng)絡(luò)帶寬增長一倍時的行為。綠線為網(wǎng)絡(luò)中包的數(shù)量,藍(lán)線為延遲
當(dāng)網(wǎng)絡(luò)帶寬降低一半的時候,多出來的包占用了 buffer,導(dǎo)致網(wǎng)絡(luò)中包的延遲顯著增加(下圖藍(lán)線),有效帶寬降低一半。延遲是使用極小值作為估計,增加的實際延遲不會反映到估計延遲(除非在延遲探測階段,下面會講)。帶寬的估計則是使用一段滑動窗口時間內(nèi)的極大值,當(dāng)之前的估計值超時(移出滑動窗口)之后,降低一半后的有效帶寬就會變成估計帶寬。估計帶寬減半后,發(fā)送窗口減半,發(fā)送端沒有窗口無法發(fā)包,buffer 被逐漸排空。發(fā)送窗口與往返延遲和有效帶寬的關(guān)系。BBR 會在左右兩側(cè)的拐點之間停下,基于丟包的標(biāo)準(zhǔn) TCP 會在右側(cè)拐點停下(圖片引自 TCP BBR 論文,下同)

當(dāng)帶寬增加一倍時,BBR 僅用 1.5 秒就收斂了;而當(dāng)帶寬降低一半時,BBR 需要 4 秒才能收斂。前者由于帶寬增長是指數(shù)級的;后者主要是由于帶寬估計采用滑動窗口內(nèi)的極大值,需要一定時間有效帶寬的下降才能反饋到帶寬估計中。
當(dāng)網(wǎng)絡(luò)帶寬保持不變的時候,穩(wěn)定狀態(tài)下的 TCP BBR 是下圖這樣的:(我們前面看到過這張圖)可見每 8 個往返延遲為周期的延遲細(xì)微變化。

往返延遲隨時間的變化。紅線:標(biāo)準(zhǔn) TCP;綠線:TCP BBR
上面介紹了 BBR 穩(wěn)定狀態(tài)下的帶寬探測階段,那么什么時候探測延遲呢?在帶寬探測階段中,估計延遲始終是使用極小值,如果實際延遲真的增加了怎么辦?TCP BBR 每過 10 秒,如果估計延遲沒有改變(也就是沒有發(fā)現(xiàn)一個更低的延遲),就進(jìn)入延遲探測階段。延遲探測階段持續(xù)的時間僅為 200 毫秒(或一個往返延遲,如果后者更大),這段時間里發(fā)送窗口固定為 4 個包,也就是幾乎不發(fā)包。這段時間內(nèi)測得的最小延遲作為新的延遲估計。也就是說,大約有 2% 的時間 BBR 用極低的發(fā)包速率來測量延遲。
TCP BBR 還使用 pacing 的方法降低發(fā)包時的 burstiness,減少突然傳輸?shù)囊淮鼘?dǎo)致緩沖區(qū)膨脹。發(fā)包的 burstiness 可能由兩個原因引起:
數(shù)據(jù)接收方為了節(jié)約帶寬,把多個確認(rèn)(ACK)包累積成一個發(fā)出,這叫做 ACK Compression。數(shù)據(jù)發(fā)送方收到這個累積確認(rèn)包后,如果沒有 pacing,就會發(fā)出一連串的數(shù)據(jù)包。
數(shù)據(jù)發(fā)送方?jīng)]有足夠的數(shù)據(jù)可傳輸,積累了一定量的空閑發(fā)送窗口。當(dāng)應(yīng)用層突然需要傳輸較多的數(shù)據(jù)時,如果沒有 pacing,就會把空閑發(fā)送窗口大小這么多數(shù)據(jù)一股腦發(fā)出去。
下面我們來看 TCP BBR 的效果如何。
首先看 BBR 試圖解決的第一個問題:在有隨機丟包情況下的吞吐量。如下圖所示,只要有萬分之一的丟包率,標(biāo)準(zhǔn) TCP 的帶寬就只剩 30%;千分之一丟包率時只剩 10%;有百分之一的丟包率時幾乎就卡住了。而 TCP BBR 在丟包率 5% 以下幾乎沒有帶寬損失,在丟包率 15% 的時候仍有 75% 帶寬。網(wǎng)絡(luò)帶寬降低一半時的行為。綠線為網(wǎng)絡(luò)中包的數(shù)量,藍(lán)線為延遲

100 Mbps,100ms 下的丟包率和有效帶寬(紅線:標(biāo)準(zhǔn) TCP,綠線:TCP BBR)
異地數(shù)據(jù)中心間跨廣域網(wǎng)的傳輸往往是高帶寬、高延遲的,且有一定丟包率,TCP BBR 可以顯著提高傳輸速度。這也是中國科大 LUG HTTP 代理服務(wù)器和 Google 廣域網(wǎng)(B4)部署 TCP BBR 的主要原因。
再來看 BBR 試圖解決的第二個問題:降低延遲,減少緩沖區(qū)膨脹。如下圖所示,標(biāo)準(zhǔn) TCP 傾向于把緩沖區(qū)填滿,緩沖區(qū)越大,延遲就越高。當(dāng)用戶的網(wǎng)絡(luò)接入速度很慢時,這個延遲可能超過操作系統(tǒng)連接建立的超時時間,導(dǎo)致連接建立失敗。使用 TCP BBR 就可以避免這個問題。

緩沖區(qū)大小與延遲的關(guān)系(紅線:標(biāo)準(zhǔn) TCP,綠線:TCP BBR)
Youtube 部署了 TCP BBR 之后,全球范圍的中位數(shù)延遲降低了 53%(也就是快了一倍),發(fā)展中國家的中位數(shù)延遲降低了 80%(也就是快了 4 倍)。從下圖可見,延遲越高的用戶,采用 TCP BBR 后的延遲下降比例越高,原來需要 10 秒的現(xiàn)在只要 2 秒了。如果您的網(wǎng)站需要讓用 GPRS 或者慢速 WiFi 接入網(wǎng)絡(luò)的用戶也能流暢訪問,不妨試試 TCP BBR。

標(biāo)準(zhǔn) TCP 與 TCP BBR 的往返延遲中位數(shù)之比
綜上,TCP BBR 不再使用丟包作為擁塞的信號,也不使用 “加性增,乘性減” 來維護(hù)發(fā)送窗口大小,而是分別估計極大帶寬和極小延遲,把它們的乘積作為發(fā)送窗口大小。
BBR 的連接開始階段由慢啟動、排空兩階段構(gòu)成。為了解決帶寬和延遲不易同時測準(zhǔn)的問題,BBR 在連接穩(wěn)定后交替探測帶寬和延遲,其中探測帶寬階段占絕大部分時間,通過正反饋和周期性的帶寬增益嘗試來快速響應(yīng)可用帶寬變化;偶爾的探測延遲階段發(fā)包速率很慢,用于測準(zhǔn)延遲。
BBR 解決了兩個問題:
在有一定丟包率的網(wǎng)絡(luò)鏈路上充分利用帶寬。非常適合高延遲、高帶寬的網(wǎng)絡(luò)鏈路。
降低網(wǎng)絡(luò)鏈路上的 buffer 占用率,從而降低延遲。非常適合慢速接入網(wǎng)絡(luò)的用戶。
看到評論區(qū)很多客戶端和服務(wù)器哪個部署 TCP BBR 有效的問題,需要提醒:TCP 擁塞控制算法是數(shù)據(jù)的發(fā)送端決定發(fā)送窗口,因此在哪邊部署,就對哪邊發(fā)出的數(shù)據(jù)有效。如果是下載,就應(yīng)在服務(wù)器部署;如果是上傳,就應(yīng)在客戶端部署。
如果希望加速訪問國外網(wǎng)站的速度,且下載流量遠(yuǎn)高于上傳流量,在客戶端上部署 TCP BBR(或者任何基于 TCP 擁塞控制的加速算法)是沒什么效果的。需要在 VPN 的國外出口端部署 TCP BBR,并做 TCP Termination & TCP Proxy。也就是客戶建立連接事實上是跟 VPN 的國外出口服務(wù)器建聯(lián),國外出口服務(wù)器再去跟目標(biāo)服務(wù)器建聯(lián),使得丟包率高、延遲大的這一段(從客戶端到國外出口)是部署了 BBR 的國外出口服務(wù)器在發(fā)送數(shù)據(jù)。或者在 VPN 的國外出口端部署 BBR 并做 HTTP(S) Proxy,原理相同。
大概是由于 ACM queue 的篇幅限制和目標(biāo)讀者,這篇論文并沒有討論(僅有擁塞丟包情況下)TCP BBR 與標(biāo)準(zhǔn) TCP 的公平性。也沒有討論 BBR 與現(xiàn)有擁塞控制算法的比較,如基于往返延遲的(如 TCP Vegas)、綜合丟包和延遲因素的(如 Compound TCP、TCP Westwood+)、基于網(wǎng)絡(luò)設(shè)備提供擁塞信息的(如 ECN)、網(wǎng)絡(luò)設(shè)備采用新調(diào)度策略的(如 CoDel)。期待 Google 發(fā)表更詳細(xì)的論文,也期待各位同行報告 TCP BBR 在實驗或生產(chǎn)環(huán)境中的性能。
本人不是 TCP 擁塞控制領(lǐng)域的專家,如有錯漏不當(dāng)之處,懇請指正。
[1] Cardwell, Neal, et al. “BBR: Congestion-Based Congestion Control.”?Queue14.5 (2016): 50.
本文固定鏈接:?http://zoufeng.net/2017/06/22/google-bbr/
轉(zhuǎn)載請聯(lián)系原作者??2017年06月22日?于?foam?發(fā)表