Linux Kernel 4.9 中的 BBR 演算法與之前的 TCP 擁塞控制相比有什麼優勢?


中國科大 LUG 的 @高一凡 在 LUG HTTP 代理伺服器上部署了 Linux 4.9 的 TCP BBR 擁塞控制演算法。從科大的移動出口到新加坡 DigitalOcean 的實測下載速度從 647 KB/s 提高到了 22.1 MB/s(截屏如下)。

(應評論區各位 dalao 要求,補充測試環境說明:是在新加坡的伺服器上設置了 BBR,新加坡的伺服器是數據的發送方。這個伺服器是訪問牆外資源的 HTTP 代理。科大移動出口到 DigitalOcean 之間不是 dedicated 的專線,是走的公網,科大移動出口這邊是 1 Gbps 無限速(但是要跟其他人 share),DigitalOcean 實測是限速 200 Mbps。RTT 是 66 ms。實測結果這麼好,也是因為大多數人用的是 TCP Cubic (Linux) / Compound TCP (Windows),在有一定丟包率的情況下,TCP BBR 更加激進,搶佔了更多的公網帶寬。因此也是有些不道德的感覺。)

此次 Google 提交到 Linux 主線並發表在 ACM queue 期刊上的 TCP BBR 擁塞控制演算法,繼承了 Google 「先在生產環境部署,再開源和發論文」 的研究傳統。TCP BBR 已經在 Youtube 伺服器和 Google 跨數據中心的內部廣域網(B4)上部署。

TCP BBR 致力於解決兩個問題:

  1. 在有一定丟包率的網路鏈路上充分利用帶寬。
  2. 降低網路鏈路上的 buffer 佔用率,從而降低延遲。

TCP 擁塞控制的目標是最大化利用網路上瓶頸鏈路的帶寬。一條網路鏈路就像一條水管,要想用滿這條水管,最好的辦法就是給這根水管灌滿水,也就是:
水管內的水的數量 = 水管的容積 = 水管粗細 × 水管長度
換成網路的名詞,也就是:
網路內尚未被確認收到的數據包數量 = 網路鏈路上能容納的數據包數量 = 鏈路帶寬 × 往返延遲

TCP 維護一個發送窗口,估計當前網路鏈路上能容納的數據包數量,希望在有數據可發的情況下,回來一個確認包就發出一個數據包,總是保持發送窗口那麼多個包在網路中流動。

TCP 與水管的類比示意(圖片來源:Van Jacobson,Congestion Avoidance and Control,1988)

如何估計水管的容積呢?一種大家都能想到的方法是不斷往裡灌水,直到溢出來為止。標準 TCP 中的擁塞控制演算法也類似:不斷增加發送窗口,直到發現開始丟包。這就是所謂的 」加性增,乘性減」,也就是當收到一個確認消息的時候慢慢增加發送窗口,當確認一個包丟掉的時候較快地減小發送窗口。

標準 TCP 的這種做法有兩個問題:

首先,假定網路中的丟包都是由於擁塞導致(網路設備的緩衝區放不下了,只好丟掉一些數據包)。事實上網路中有可能存在傳輸錯誤導致的丟包,基於丟包的擁塞控制演算法並不能區分擁塞丟包錯誤丟包。在數據中心內部,錯誤丟包率在十萬分之一(1e-5)的量級;在廣域網上,錯誤丟包率一般要高得多。

更重要的是,「加性增,乘性減」 的擁塞控制演算法要能正常工作,錯誤丟包率需要與發送窗口的平方成反比。數據中心內的延遲一般是 10-100 微秒,帶寬 10-40 Gbps,乘起來得到穩定的發送窗口為 12.5 KB 到 500 KB。而廣域網上的帶寬可能是 100 Mbps,延遲 100 毫秒,乘起來得到穩定的發送窗口為 10 MB。廣域網上的發送窗口比數據中心網路高 1-2 個數量級,錯誤丟包率就需要低 2-4 個數量級才能正常工作。因此標準 TCP 在有一定錯誤丟包率的長肥管道(long-fat pipe,即延遲高、帶寬大的鏈路)上只會收斂到一個很小的發送窗口。這就是很多時候客戶端和伺服器都有很大帶寬,運營商核心網路也沒佔滿,但下載速度很慢,甚至下載到一半就沒速度了的一個原因。

其次,網路中會有一些 buffer,就像輸液管里中間膨大的部分,用於吸收網路中的流量波動。由於標準 TCP 是通過 「灌滿水管」 的方式來估算髮送窗口的,在連接的開始階段,buffer 會被傾向於佔滿。後續 buffer 的佔用會逐漸減少,但是並不會完全消失。客戶端估計的水管容積(發送窗口大小)總是略大於水管中除去膨大部分的容積。這個問題被稱為 bufferbloat(緩衝區膨脹)

緩衝區膨脹現象圖示緩衝區膨脹有兩個危害:

  1. 增加網路延遲。buffer 裡面的東西越多,要等的時間就越長嘛。
  2. 共享網路瓶頸的連接較多時,可能導致緩衝區被填滿而丟包。很多人把這種丟包認為是發生了網路擁塞,實則不然。

往返延遲隨時間的變化。紅線:標準 TCP(可見周期性的延遲變化,以及 buffer 幾乎總是被填滿);綠線:TCP BBR
(圖片引自 Google 在 ACM queue 2016 年 9-10 月刊上的論文 [1],下同)

有很多論文提出在網路設備上把當前緩衝區大小的信息反饋給終端,比如在數據中心廣泛應用的 ECN(Explicit Congestion Notification)。然而廣域網上網路設備眾多,更新換代困難,需要網路設備介入的方案很難大範圍部署。

TCP BBR 是怎樣解決以上兩個問題的呢?

  1. 既然不容易區分擁塞丟包和錯誤丟包,TCP BBR 就乾脆不考慮丟包。
  2. 既然灌滿水管的方式容易造成緩衝區膨脹,TCP BBR 就分別估計帶寬和延遲,而不是直接估計水管的容積。

帶寬和延遲的乘積就是發送窗口應有的大小。發明於 2002 年並已進入 Linux 內核的 TCP Westwood 擁塞控制演算法,就是分別估計帶寬和延遲,並計算其乘積作為發送窗口。然而帶寬和延遲就像粒子的位置和動量,是沒辦法同時測準的:要測量最大帶寬,就要把水管灌滿,緩衝區中有一定量的數據包,此時延遲就是較高的;要測量最低延遲,就要保證緩衝區為空,網路里的流量越少越好,但此時帶寬就是較低的。

TCP BBR 解決帶寬和延遲無法同時測准的方法是:交替測量帶寬和延遲;用一段時間內的帶寬極大值和延遲極小值作為估計值。

在連接剛建立的時候,TCP BBR 採用類似標準 TCP 的慢啟動,指數增長發送速率。然而標準 TCP 遇到任何一個丟包就會立即進入擁塞避免階段,它的本意是填滿水管之後進入擁塞避免,然而(1)如果鏈路的錯誤丟包率較高,沒等到水管填滿就放棄了;(2)如果網路里有 buffer,總要把緩衝區填滿了才會放棄。

TCP BBR 則是根據收到的確認包,發現有效帶寬不再增長時,就進入擁塞避免階段。(1)鏈路的錯誤丟包率只要不太高,對 BBR 沒有影響;(2)當發送速率增長到開始佔用 buffer 的時候,有效帶寬不再增長,BBR 就及時放棄了(事實上放棄的時候占的是 3 倍帶寬 × 延遲,後面會把多出來的 2 倍 buffer 清掉),這樣就不會把緩衝區填滿。

發送窗口與往返延遲和有效帶寬的關係。BBR 會在左右兩側的拐點之間停下,基於丟包的標準 TCP 會在右側拐點停下(圖片引自 TCP BBR 論文,下同)

在慢啟動過程中,由於 buffer 在前期幾乎沒被佔用,延遲的最小值就是延遲的初始估計;慢啟動結束時的最大有效帶寬就是帶寬的初始估計。

慢啟動結束後,為了把多佔用的 2 倍帶寬 × 延遲消耗掉,BBR 將進入排空(drain)階段,指數降低發送速率,此時 buffer 里的包就被慢慢排空,直到往返延遲不再降低。如下圖綠線所示。

TCP BBR(綠線)與標準 TCP(紅線)有效帶寬和往返延遲的比較

排空階段結束後,BBR 進入穩定運行狀態,交替探測帶寬和延遲。由於網路帶寬的變化比延遲的變化更頻繁,BBR 穩定狀態的絕大多數時間處於帶寬探測階段。帶寬探測階段是一個正反饋系統:定期嘗試增加發包速率,如果收到確認的速率也增加了,就進一步增加發包速率。

具體來說,以每 8 個往返延遲為周期,在第一個往返的時間裡,BBR 嘗試增加發包速率 1/4(即以估計帶寬的 5/4 速度發送)。在第二個往返的時間裡,為了把前一個往返多發出來的包排空,BBR 在估計帶寬的基礎上降低 1/4 作為發包速率。剩下 6 個往返的時間裡,BBR 使用估計的帶寬發包。

當網路帶寬增長一倍的時候,每個周期估計帶寬會增長 1/4,每個周期為 8 個往返延遲。其中向上的尖峰是嘗試增加發包速率 1/4,向下的尖峰是降低發包速率 1/4(排空階段),後面 6 個往返延遲,使用更新後的估計帶寬。3 個周期,即 24 個往返延遲後,估計帶寬達到增長後的網路帶寬。

網路帶寬增長一倍時的行為。綠線為網路中包的數量,藍線為延遲

當網路帶寬降低一半的時候,多出來的包佔用了 buffer,導致網路中包的延遲顯著增加(下圖藍線),有效帶寬降低一半。延遲是使用極小值作為估計,增加的實際延遲不會反映到估計延遲(除非在延遲探測階段,下面會講)。帶寬的估計則是使用一段滑動窗口時間內的極大值,當之前的估計值超時(移出滑動窗口)之後,降低一半後的有效帶寬就會變成估計帶寬。估計帶寬減半後,發送窗口減半,發送端沒有窗口無法發包,buffer 被逐漸排空。

網路帶寬降低一半時的行為。綠線為網路中包的數量,藍線為延遲

當帶寬增加一倍時,BBR 僅用 1.5 秒就收斂了;而當帶寬降低一半時,BBR 需要 4 秒才能收斂。前者由於帶寬增長是指數級的;後者主要是由於帶寬估計採用滑動窗口內的極大值,需要一定時間有效帶寬的下降才能反饋到帶寬估計中。

當網路帶寬保持不變的時候,穩定狀態下的 TCP BBR 是下圖這樣的:(我們前面看到過這張圖)可見每 8 個往返延遲為周期的延遲細微變化。

往返延遲隨時間的變化。紅線:標準 TCP;綠線:TCP BBR

上面介紹了 BBR 穩定狀態下的帶寬探測階段,那麼什麼時候探測延遲呢?在帶寬探測階段中,估計延遲始終是使用極小值,如果實際延遲真的增加了怎麼辦?TCP BBR 每過 10 秒,如果估計延遲沒有改變(也就是沒有發現一個更低的延遲),就進入延遲探測階段。延遲探測階段持續的時間僅為 200 毫秒(或一個往返延遲,如果後者更大),這段時間裡發送窗口固定為 4 個包,也就是幾乎不發包。這段時間內測得的最小延遲作為新的延遲估計。也就是說,大約有 2% 的時間 BBR 用極低的發包速率來測量延遲

TCP BBR 還使用 pacing 的方法降低發包時的 burstiness,減少突然傳輸的一串包導致緩衝區膨脹。發包的 burstiness 可能由兩個原因引起:

  1. 數據接收方為了節約帶寬,把多個確認(ACK)包累積成一個發出,這叫做 ACK Compression。數據發送方收到這個累積確認包後,如果沒有 pacing,就會發出一連串的數據包。
  2. 數據發送方沒有足夠的數據可傳輸,積累了一定量的空閑發送窗口。當應用層突然需要傳輸較多的數據時,如果沒有 pacing,就會把空閑發送窗口大小這麼多數據一股腦發出去。

下面我們來看 TCP BBR 的效果如何。

首先看 BBR 試圖解決的第一個問題:在有隨機丟包情況下的吞吐量。如下圖所示,只要有萬分之一的丟包率,標準 TCP 的帶寬就只剩 30%;千分之一丟包率時只剩 10%;有百分之一的丟包率時幾乎就卡住了。而 TCP BBR 在丟包率 5% 以下幾乎沒有帶寬損失,在丟包率 15% 的時候仍有 75% 帶寬

100 Mbps,100ms 下的丟包率和有效帶寬(紅線:標準 TCP,綠線:TCP BBR)

異地數據中心間跨廣域網的傳輸往往是高帶寬、高延遲的,且有一定丟包率,TCP BBR 可以顯著提高傳輸速度。這也是中國科大 LUG HTTP 代理伺服器和 Google 廣域網(B4)部署 TCP BBR 的主要原因。

再來看 BBR 試圖解決的第二個問題:降低延遲,減少緩衝區膨脹。如下圖所示,標準 TCP 傾向於把緩衝區填滿,緩衝區越大,延遲就越高。當用戶的網路接入速度很慢時,這個延遲可能超過操作系統連接建立的超時時間,導致連接建立失敗。使用 TCP BBR 就可以避免這個問題。

緩衝區大小與延遲的關係(紅線:標準 TCP,綠線:TCP BBR)

Youtube 部署了 TCP BBR 之後,全球範圍的中位數延遲降低了 53%(也就是快了一倍),發展中國家的中位數延遲降低了 80%(也就是快了 4 倍)。從下圖可見,延遲越高的用戶,採用 TCP BBR 後的延遲下降比例越高,原來需要 10 秒的現在只要 2 秒了。如果您的網站需要讓用 GPRS 或者慢速 WiFi 接入網路的用戶也能流暢訪問,不妨試試 TCP BBR。

標準 TCP 與 TCP BBR 的往返延遲中位數之比

綜上,TCP BBR 不再使用丟包作為擁塞的信號,也不使用 「加性增,乘性減」 來維護髮送窗口大小,而是分別估計極大帶寬和極小延遲,把它們的乘積作為發送窗口大小。


BBR 的連接開始階段由慢啟動、排空兩階段構成。為了解決帶寬和延遲不易同時測準的問題,BBR 在連接穩定後交替探測帶寬和延遲,其中探測帶寬階段占絕大部分時間,通過正反饋和周期性的帶寬增益嘗試來快速響應可用帶寬變化;偶爾的探測延遲階段發包速率很慢,用於測准延遲。

BBR 解決了兩個問題:

  1. 在有一定丟包率的網路鏈路上充分利用帶寬。非常適合高延遲、高帶寬的網路鏈路。
  2. 降低網路鏈路上的 buffer 佔用率,從而降低延遲。非常適合慢速接入網路的用戶。

看到評論區很多客戶端和伺服器哪個部署 TCP BBR 有效的問題,需要提醒:TCP 擁塞控制演算法是數據的發送端決定發送窗口,因此在哪邊部署,就對哪邊發出的數據有效。如果是下載,就應在伺服器部署;如果是上傳,就應在客戶端部署。

如果希望加速訪問國外網站的速度,且下載流量遠高於上傳流量,在客戶端上部署 TCP BBR(或者任何基於 TCP 擁塞控制的加速演算法)是沒什麼效果的。需要在 VPN 的國外出口端部署 TCP BBR,並做 TCP Termination TCP Proxy。也就是客戶建立連接事實上是跟 VPN 的國外出口伺服器建聯,國外出口伺服器再去跟目標伺服器建聯,使得丟包率高、延遲大的這一段(從客戶端到國外出口)是部署了 BBR 的國外出口伺服器在發送數據。或者在 VPN 的國外出口端部署 BBR 並做 HTTP(S) Proxy,原理相同。

大概是由於 ACM queue 的篇幅限制和目標讀者,這篇論文並沒有討論(僅有擁塞丟包情況下)TCP BBR 與標準 TCP 的公平性。也沒有討論 BBR 與現有擁塞控制演算法的比較,如基於往返延遲的(如 TCP Vegas)、綜合丟包和延遲因素的(如 Compound TCP、TCP Westwood+)、基於網路設備提供擁塞信息的(如 ECN)、網路設備採用新調度策略的(如 CoDel)。期待 Google 發表更詳細的論文,也期待各位同行報告 TCP BBR 在實驗或生產環境中的性能。

本人不是 TCP 擁塞控制領域的專家,如有錯漏不當之處,懇請指正。

[1] Cardwell, Neal, et al. "BBR: Congestion-Based Congestion Control." Queue14.5 (2016): 50.


@李博傑的回答,寫得很棒,已經回答得很詳細了,我也來粗略說一下我的理解,有不妥之處還請指出。
我自己對BBR的總結就是:終於轉變了對「擁塞「這個概念的理解,經典的擁塞控制演算法比如reno/newReno/Cubic無一例外都是將丟包作為擁塞的信號,然後降低發送速率。而在該演算法中,不考慮丟包,而是基於這樣一個定義:當網路上的包數大於BDP(帶寬時延乘積)時,就認為出現了擁塞。所以重點就在於如何準確地測量出瓶頸鏈路的帶寬和整個鏈路的傳播時延。
在1980年設計擁塞控制演算法的時候,將擁塞等同於丟包沒有很大問題的,當時路由器的緩存小,鏈路帶寬也不高。但是現在,路由器的緩存已經很大了,基於丟包的擁塞演算法會一直增加窗口,直至把瓶頸路徑上的路由緩存填滿,然後出現丟包。但是,在這個過程中時延已經增大到我們無法容忍的程度了,所以需要反思這種基於丟包的擁塞控制思想。
因為網路對TCP連接的兩端來說是一個黑盒,沒有明顯的信息告訴我們說網路出現了擁塞(支持ECN的路由設備在現網中的普及率不高 ),所以我們只能通過反饋來推測的,這也就是為啥需要擁塞控制演算法的原因之一了。
這個演算法的實現也有一個重大的思路轉變,那就是不能僅僅只控制發多少包,也就是用擁塞窗口cwnd和慢啟動門限值ssthresh來控制發包的多少,我們還應該控制發包的速率,所以pacing_rate成為主要控制因素。
另外,這篇論文的出現也印證了我們的一個思路是可行的:丟包恢復和窗口管理解耦。如果我們發現有丟包,重傳就好了嘛,至於發送速率如何調整,全部交給擁塞控制演算法就好了。

這裡回答一下 @行功的幾個問題。
2. BBR的「測不準」是個什麼鬼?
這裡指的是RTprop和BtlBW不能同時測得。

RTprop指的是鏈路的傳播時延,也就是等於路徑長度 / 信號傳播速率,只有在鏈路上沒有任何排隊和其他時延的時候,才能有RTT來近似。因此, inflight(在途數據包數)要小於BDP。而BtlBW是瓶頸鏈路的帶寬,只有當發的包數&>= BDP時,才能用發送速率來近似。因此這個兩個值不能同時得到。從這幅圖可以很清楚地看出,RTprop是當amout inflight &< 最優點測得;BtlBw是 amout inflight &> 最優點測得。
3. BBR號稱的primary control的探測帶寬有用么?
首先我們要知道對於一條連接來說,它的可用帶寬是什麼,當它獨佔整個鏈路時,它的可用帶寬就近似為鏈路的物理帶寬,但多條流共享鏈路時,最理想最公平的肯定是BW/n。但是這個我們並不知道,只能通過一點一點地發包探測,比如可以先發快一點,發現出現擁塞了就發慢一點,這樣反覆探測直到收斂。就如下圖所示:

4. BBR到底是什麼?

「BBR真正起作用是它放第二位的CWND=bw*PropRTT控制。「

這句話我不敢苟同。因為在論文中說的以pacing_rate作為主要控制手段。在內核代碼中我們可以看到sock結構體中有一個域是sk_pacing_rate。
同時我們也看到tcp_bbr.c里有這麼一段注釋:

* NOTE: BBR *must* be used with the fq qdisc ("man tc-fq") with pacing enabled,
* since pacing is integral to the BBR design and implementation.
* BBR without pacing would not function properly, and may incur unnecessary
* high packet loss rates.
*/

並參考該鏈接:TSO sizing and the FQ scheduler里有這麼一句話:

That transmission time is used to implement the TCP pacing support. If a given socket has a pace specified for it, FQ will calculate how far the packets should be spaced in time to conform to that pace.

所以我個人目前理解的是pacing是通過將sock中的sk_pacing_rate傳遞給FQ scheduler來實現的。由於我沒有完全跟過這個代碼實現的全過程,所以不能完全肯定pacing是如何具體實現的。但是可以看出用pacing來控制發包速率是完全可行的。


在探討這個問題之前,關於網路中的Bufferbloat問題需要了解,詳細信息在這裡(https://www.bufferbloat.net/projects/bloat/wiki/Introduction/),@李博傑 的回答也說得比較清楚了。

在這裡做一些補充吧。
流量控制分為兩部分:
* 接收方的流量控制(即滑動窗口)-- 由接收方告知,只關注自身緩存情況,不關注網路,這裡不討論。
* 發送方的流量控制(即擁塞控制)
現在廣泛使用的CUBIC/(new)Reno都是基於丟包的,在演算法上重點輸出擁塞窗口(cwnd);
而BBR輸出cwndpacing_rate,且pacing_rate為主,cwnd為輔,參考(https://groups.google.com/d/msg/bbr-dev/bIIdBU4feD8/sfmbh4W_DgAJ)

什麼是pacing?看下圖:

圖片引用來自 QUIC @ Google Developers Live, February 2014
也就是說早期的擁塞控制輸出cwnd只是告訴tcp可以發多少數據,而沒有說怎麼發,恰好,BBR輸出的pacing_rate就是告訴TCP怎麼發

BBR對TCP的大膽改動:

紅框中是BBR加入時添加的,這裡很明顯,BBR從TCP接管了充分的控制權。
之前的擁塞控制並不總是能起作用,換句話說就是會被奪權。TCP走進PRR演算法(參考論文:Proportional Rate Reduction for TCP)後,擁塞控制無能為力。
從工程實現的角度來看,BBR這個小小的修改把TCP的 可靠傳輸 / 擁塞控制 解耦了 —— TCP你專註於自己的可靠性(當然還有很多其它細節),我BBR總是會負責任地告訴你(TCP)現在可以發多少數據,以什麼速度發出這些數據。丟包對BBR有什麼影響?

圖片來自 BBR-TCP-Opportunities
從演算法上來講,丟包對BBR的影響微乎其微。BBR只管告訴TCP cwnd/pacing_rate,不管需要發送的包是重傳的還是正常發送的。看上圖,丟包率在20%的時候BBR的輸出驟降,導致這個現象其實是從實現層面考慮設置的一個閾值

/* If lost/delivered ratio &> 20%, interval is "lossy" and we may be policed: */
static const u32 bbr_lt_loss_thresh = 50;

這裡還考慮了被限速的場景,不展開。

友好性測試
@jamesr 提到的友好性問題,google groups里有測試數據
https://groups.google.com/d/msg/bbr-dev/zyvKgjjOYr8/pN20-CmVBQAJ
----------------
10 Mbps link with 40ms RTT
帶寬,RTT固定的情況下,測試不同Buffer大小的情況:

buf以n倍BDP表示,CUBIC/Vegas/BBR輸出單位Mbps
(1) 1 CUBIC flow vs. 1 Vegas flow:
buf CUBIC Vegas
---- ----- -----
0.5 6.81 2.73
1 8.49 1.06
2 9.12 0.43
4 9.15 0.4

(2) 1 CUBIC flow vs. 1 BBR flow:
buf CUBIC BBR
---- ----- -----
0.5 1.74 7.67
1 1.71 7.7
2 4.79 4.72
4 6.12 3.43

說明:
Vegas是基於延遲的擁塞控制,現在幾乎不用了,因為它們跟基於丟包的擁塞控制發生競爭時會處於幾乎餓死的狀態。
另外,關於Ledbat(基於延遲的)用於BT,是理所應當的(掛BT下載的急迫性一般是低於常規網路流量的,當有常規流量介入時,主動退避是符合常理的)。

v------------2016.12.20更新--------------v
bbr-dev郵件組中一組測試數據( @Leo Zhang 的回答中也提供了)引起了大家的關注。
最開始,Leo Zhang的回答所提到的測試報告我並未詳細閱讀。今天抽時間詳細看了一下,感到意外。
比如出現BBR餓死CUBIC,BBR餓死同類。這和其它測試數據出入很大。

我第一反應就是環境不對,BBR挑環境。然而這方面卻沒找到說明,BBR相關的文檔都沒有提到專用場景。

接著, @NeterOster 拋出了另一個問題(如何評價文章《令人躁動一時且令人不安的TCP BBR演算法》?)。看過文章(該作者之前的文章也看了),寫了簡答,才發現自己似乎錯過了什麼,同時自己其實也對20%的丟包率閾值設置有疑問,偷懶的理解就是大量測試統計的結果吧。

這些天bbr-dev中關於BBR Report(https://groups.google.com/forum/#!topic/bbr-dev/Ps4zyM5AD9g)這份精彩的郵件列表我錯過了,趕緊補一下!
Neal Cardwell 說到:

We are actively working on reducing the buffer pressure exerted by BBR,
which should help in the sorts of CUBIC vs BBR scenarios you describe
(as well as BBR vs BBR scenarios).

這份剛剛誕生的擁塞控制的確還是存在不少缺陷,不過依然在持續改進中,期待美好的事情總會發生吧!
^-------------2016.12.20更新-------------^

根據 @李博傑 的回答中已經提到的實測延遲改善數據,我們可以看到目前互聯網整體上Bufferbloat問題是比較嚴重的,即我們的網路請求延遲總體被拉高很多。
為了降低延遲,如果:
1、我們改用基於延遲的擁塞控制,因為不可能一時間全部更新,先替換的那部分網路體驗會很糟糕;
2、逐步改用BBR這類擁塞控制,我們的網路高延遲問題將會逐漸得到改善。

以上並非說一定是BBR,但是BBR在擁塞控制上開闢了一條新的路(也許早就有人做過類似的嘗試,但是因為工程實現,或者測試環境受限不能得到廣泛驗證,石沉大海),相信以後關於擁塞控制的研究改進更多會基於這條路去走。

最後,BBR是基於什麼的擁塞控制?
根據論文,是基於擁塞的擁塞控制(Congestion-based Congestion Control),但是看起來感覺不好理解。
根據我的理解,我更傾向於稱它為 基於帶寬延遲的擁塞控制(BDP-based Congestion Control)。
因為,BBR總是在測量最小RTT(10s內),最大Bandwidth(10 Round Trips),並且盡量控制輸出到網路的數據包(in-flight)靠近 BDP(without buffer),這樣既能保證帶寬利用率,又能避免Bufferbloat問題。

PS. BBR也已經被實現在QUIC協議中,參考(https://cs.chromium.org/chromium/src/net/quic/core/congestion_control/bbr_sender.h)。

我也並非完全理解了BBR的實現細節,並且其中還牽扯到TCP的實現,也不熟悉。
如果以上理解有錯,或者不到位,歡迎指正。

完。

---
XTao


一個月之前,從 Ilya Grigorik 的 Twitter 上得知 BBR 的存在,在 U2B 看完作者的公開分享視頻,以及公開 Keynote :Making_Linux_TCP_Fast

便預測這個擁塞演算法未來前途必定不可限量。果不其然,一夜之間,幾乎所有的梯子商以及各種大小站長都開始嘗鮮,這應該是既 FinalSpeed、銳速以及 KCP 之後,梯子商的又一波集體部署浪潮。

既然問題是 BBR 演算法與之前的 TCP 擁塞控制相比有什麼優勢?
技術角度以及細節就不多說啦,上面已經有人給出,就不班門弄斧了,所以這裡我提供幾份資料,希望可以給大家做些參考。

這裡有一份測試報告,來自大名鼎鼎的 Lawrence Brakmo
裡面不僅有 BBR 以及 Cubic 的比較,而且還有數據中心傳輸控制協議 DCTCP
應該是目前為止,在大規模網路應用情景下,比較有說服力的 Test Report

測試共有三個主要場景,以及兩個測試集,每一項測試都超過一分鐘:
主場景:

  • LAN with 20us RTT, 10 Gbps - servers in same rack.
  • WAN with 10ms RTT, 10 Gbps - servers in same rack, using netem for latency.
  • WAN with 10-40ms RTT, 10-40 Mbps - servers in same rack, using server as router, tbf for limiting bandwdith,netem for latency.

另外 2 個為演算法公平性和穩定性以及延遲測試

Report 地址:
Google Drive:
https://drive.google.com/file/d/0B4YZ_0yTgbJEa21CbUVLWFdrX2c/view

部分截圖如下,就不翻譯了,可以去看原文。

個人覺得,在大規模場景的網路情況下,BBR 相比於其它的擁塞控制協議(CA),有著更出色的競爭力,在一些比較惡劣的情景,再去考慮性能,這些演算法之間的取捨
就見仁見智了。

參考資料:
Keynote:
http://netdevconf.org/1.2/slides/oct5/04_Making_Linux_TCP_Fast_netdev_1.2_final.pdf

Video:
"Making Linux TCP Fast - Yuchung Cheng, Neal Cardwel"
https://www.youtube.com/watch?v=hIl_zXzU3DAt=4s

Paper:
http://netdevconf.org/1.2/papers/bbr-netdev-1.2.new.new.pdf

Other:
DCTCP


@李博傑

寫的很好。


補充一點信息,BBR使用RACK來做重傳判斷,並沒有忽略丟包,只是不用重複ACK所以更加容忍亂序。

可參考draft:

RACK: a time-based fast loss detection algorithm for TCP

同時: google 的BBR 不使用第二BDP的思想其實早在81年就有論文了 Gail, R., Kleinrock,L. 1981. 「An invariant property of computer network power.」,


只是當時的Reno或者在現在的cubic都不可能達到最理想的那個point,當時候就有論文出來抨擊 說這個理想的狀態不可能達到 具體見,Jaffe, J. 1981. Flow control power is nondecentralizable. IEEE Transactions on Communications 29

Google厲害的地方就是自己設計自動機將這個理想的狀態實現了。

他的影響力:尤其在廣域網上降低時延、減少丟包的影響等將是巨大的,好比 DCTCP 之於 DC,因為他只需要server modified,現在就是更新一下內核就行了。


不過下面的這一系列文章我認為介紹的非常全面

http://blog.csdn.net/dog250/article/details/52895080


@李博傑 說得很詳細了,稍微補充一下:

延遲估算帶寬,避免bufferbloat的演算法,人家bittorrent的μTP(LEDBAT)用了好久了,並且分析了和現有TCP發生競爭時主動退避的特性。

作為一個有志於代替默認TCP congestion control 的演算法,不比較和現有演算法共存時的公平性,就有點耍無賴的味道了。

12月18日補充:
拋磚引玉起到效果了,公平性的資料也補充了起來。

總的來說,想法是好的(估計BDP,將緩衝區利用率提高,避免Buffer Bloat,無視20%以下的丟包),結果是誘人的(Google內部實測最高提速133倍,呵呵)。
但是,它會在有丟包時嚴重餓死cubic。有點像什麼呢?有點像地面交通開汽車,主流的都是開著大卡車,遇到路況差翻車了或者追尾了就減速一倍。而BBR是開著小電驢,奔著等紅綠燈時間最少調整自己的速度,路況差,電驢多了免不了大量出事故,但BBR認為事故率在20%以下都是路況差而不是自己發車太多導致的追尾。
兩種一起發車時,大卡車總是撞到翻車的小電驢,總是沒法加速,開在最慢速度慢慢爬。

接下來會怎麼樣呢?很有可能是大卡車爭先恐後地全改小電驢了。但是人家微軟家,蘋果家都沒有小電驢生產線啊 。相反Google坐擁全球最多的大卡車生產廠,又發明了小電驢,分分鐘全改小電驢廠了。按Google的體量,如果他率先大規模換BBR,按BBR打得cubic寸步難行的特性,其他廠要被逼著換BBR了,互聯網交通規則就真的會被改寫了。

現在在我看來最說不清楚的就是那個丟包20%的cutoff,這意味著BBR理論上會產生20%的垃圾數據。無論如何,大規模的BBR實踐將會帶來一場災難。


粗略看了一下,這個演算法是把TCP兩個功能分開處理:TCP主要有兩個功能:一是保證deliver,涉及很多不同的回傳方式。另外一個是congestion control,擁塞控制。當然主要TCP的改進都是在擁塞控制上,這個演算法應該也是主要在擁塞控制,問題的場景前面大家都講得很清楚,不過不知道這個TCP演算法會不會導致用傳統的比如TCP newreno的效率降低?畢竟TCP歸根到底不僅僅是最大化效率,而是在效率和公平中折中,proportional fairness,或者盡量實現帕累托最優


傳輸多少數據和傳輸什麼數據是兩件事,所謂「上帝的事情上帝管,凱撒的事情凱撒管」。在bbr中,它定義了4中狀態,即STARTUP,DRAIN,PROBE_BW,PROBE_RTT。bbr通過對上述計算的即時帶寬bw以及rtt的持續觀察,在這4個狀態之間自由切換,相比之前的所有擁塞控制演算法,其革命性的改進在於bbr擁塞演算法不再跟蹤系統的TCP擁塞狀態機,而旨在用統一的方式來應對pacing rate和cwnd的計算,不管當前TCP是處在Open狀態還是處在Disorder狀態,抑或已經在Recovery狀態,它能看到的就是bw和rtt。另外,在計算bw和rtt時,擯棄了一堆什麼指數加權之類的做法,直接用最真實的值而避免所謂的高效預測。上面提到的很多疑點,其實看看文章和代碼,就會發現,bbr在概念和出發點上有很大的突破的。正如文章里說的,因為Jeffrey M. Jaffe證明了「it was impossible to create a distributed algorithm that converged to this operating point. 」,從而導致這些年來「This result changed the direction of research from finding a distributed algorithm that achieved Kleinrock』s optimal operating point to investigating different approaches to congestion control.」 GG最後通過大量的實測數據,發現一些規律,從而以較高概率去逼近最優點,從而有了bbr。擁塞控制是一個公說公有理婆說婆有理的東西,有自知之明很重要,取其精華去其糟粕,一起好好學習吧~


2017.4.12補充: 最近很忙,一直沒顧上回答大家的問題@李博傑 @黃寧晶 @jamesr 。今天補上一篇,完成我的作業(參見:BBR是個什麼鬼?-2 外皮後的真相 - 知乎專欄)

補充:對BBR進行了一系列技術分析,解釋為什麼得出下面的結論(參見:BBR是個什麼鬼?-1 帶寬與RTT探測)

@李博傑 @黃寧晶 @jamesr ,補充一下我們對BBR的測試和理解, 供大家拍磚:

1. BBR能否忽略丟包, 提高帶寬利用率,降低延遲?
Yes。我們下面的測試結果可證明這一點。
but 很多delay-based TCP協議都可以做到這一點,例如TCP Vegas, Ledbat, TCP FAST,Google WebRTC等等。。。。

2. BBR的「測不準」是個什麼鬼?
Kleirock說的bandwidth和delay無法同時測量,指的是物理鏈路帶寬和延遲。當管子不滿時,可測出物理延遲,帶寬上限當然不知道。當管子溢出了,可測出物理帶寬,但多了排隊延遲了,這就是「測不準」的由來。可是明知測不準,為什麼BBR還要測?呵呵,有問題,事怪必妖!

3. BBR號稱的primary control的探測帶寬有用么?
BBR聲稱其primary control是探測帶寬,排第二位的是CWND擁塞窗口控制, 對這個說法我只能呵呵了~~ 。
當多個用戶共享一個帶寬時,你能探測出什麼?物理帶寬被N個人分享,上帝都不知道N是多少,我怎麼知道該分多少帶寬?

4. BBR到底是什麼?
BBR真正起作用是它放第二位的CWND=bw*PropRTT控制。 呵呵,這就有意思了,這和TCP Cubic, Vegas等等,似乎沒多大差別么。
yes,他們的差別在於目標CWND大小不同,例如Cuibc是0.75T_max, Vegas是PropRTT+a(排隊數量), LEDBAT和Google WebRTC是給定一個目標T......。等等,最後這個怎麼這聽上去和BBR一樣?
yes, BBR不僅與LEDBAT一樣,也與他們自己家的WebRTC一樣,差別在於前者用物理延遲PropRTT為目標,後兩者用排隊延遲為目標。

5. BBR存在哪些問題?
一句話,LEDBAT和WebRTC有的問題,它都有。除了一點,BBR用probRTT冷啟動機制保證了自己-自己競爭的公平性。但在於CUBIC在一起時,呵呵, 結果就不忍目睹了........

@Curtank Zhang, 看完上面是不是發現現在出生也不晚,你還是能發ACM地.......

附圖是我們( @行功 )對幾個協議的測試結果。


我主要是針對李博傑回答中的提到的一張圖做一點補充,方便大家理解。

原論文地址 : BBR: Congestion-Based Congestion Control

原論文講的非常的詳細易懂,當了回翻譯。

這張圖是說明了tcp發送速度和對應的延遲時間在數據量逐漸增大的過程中的變化。(這裡的數據是指in flight的數據,也就是在管道中的信息)


這分析這張圖之前,先解釋一個概念——緩衝區。理論上一個管道的容量是確定的。比如只能容納1MB的數據,但是實際上它最多能容納不止1MB的數據,可能是2MB或者3MB或者更多,多餘的數據被存放在緩衝區中。可以看到,圖中的 」optimum operating point」 對應的橫坐標就是管道的理論容量,也就是最優值。而圖中的」loss-based congestion control operates here」橫坐標對應的量是把管道中的緩存區都完全撐滿的數據量。


然後看這張圖。圖中剛開始是藍實線描述的階段。這時數據很少,傳輸延遲保持不動,傳輸速度不斷增加,直至到達左邊的最優點。這是因為應用傳輸的數據量太少,還沒達到物理帶寬的上限。也就是圖中所說的app limit,這段時間不用擁塞控制,隨便你怎麼發送。


這裡解釋一下為什麼這個點是最優點。比如說有一條隊伍有50人排隊,一條隊伍有100人排隊。假設平均一個窗口每小時能處理50人,所以在一小時內這兩個窗口都處理了50人的事情。但是100人的隊伍中的後50人等待的時間變長了,也就是對應的RTP變長了。簡單一看好像也沒什麼不好,讓數據在那裡排隊也沒什麼關係。但實際上緩存區設計的目的不是為了讓你這麼使用的,而是為了暫存一下發送的太快的數據的,防止數據被扔掉。而當緩存區一直處於塞滿的狀態時,假設這時有新的數據過來,沒地方存儲,那就只能把數據扔掉了,也就是所謂的丟包。丟包後,這個數據又要面臨重傳,造成很多問題。


但為什麼不都按照最優值來發送呢?事實上要找到這個最優點是非常難的。網路是個黑匣子,你很難探測到真正的管道大小。但這也正是這個BBR協議的牛逼之處。


對於找到最優值,以往的協議比如CUBIC等,都是基於這樣一個假設:網路中的緩衝區是非常小的。也就是說,只要我不斷往這個管道塞東西,塞到塞不下為止。那麼我就知道這個管道的容積了。這個假設一直是正確的,直到內存條變成了白菜價。也就是現在緩存區的平均值已經約是管道容積的兩倍了。這樣的環境明顯脫離了當時協議設計者的本意,這樣的協議已經不適用了。但是苦於沒有方法準確估計真實管道的大小,所以只能一直沿用至今。


最後,對於圖中中間的這兩段綠色實線也就很好解釋了。隨著管道堆積的數據越來越多,每份數據都要等待更長的時間。因此RTP的值越來越大。最終,管道的容積達到那個最大值,也就是緩衝區的上限,不再增長。

具體BBR是怎麼找出那個最優值的,李博傑的回答已經講的非常非常清楚了。


最後強烈建議看下論文,雖然看起來有34頁,後面全是圖片。: )

原論文地址 : BBR: Congestion-Based Congestion Control


忘了TCP協議的可以看這個回憶一下。

TCP 的那些事兒(上) | | 酷 殼 - CoolShell

還有一篇測試報告:

A quick look at TCP BBR


hello 大家好 我是白潔~ 今天我們學習~~
網路環境:聯通200m+ ss 日本機房 (聯通出國速度不是蓋的 目前最好)
訪問 youtube
bbr前:connection speed:1000kbps

bbr後
connecton speed:3332 kbps
That"s great!Thanks Ibrother!

上幾張其他的
老友記 4971

男友1預告片5020

以上都是觀看穩定的數值
其他:
湯不熱app載入視頻明顯加快了……
問題:
1.kernel 4.9 目前不是穩定版內核
2.銳速和net speeder 破壞公平性 不知道 bbr 咋樣


具體實現一下理解不透,但個人這樣理解它的目的

類比前提
鏈路+加設備buffer流動的數據流 ~ 車道數量固定的馬路上流動的車流

延遲
buffer中等待/堵車(宏觀車速降低)

吞吐
由帶寬/車道數量 與 buffer等待/堵車 共同決定

BBR 所想做的事情:
盡量排空設備Buffer/提高車速到車道限速

到達的效果
網路設備buffer被儘可能排空,數據包沒有額外延遲,然後由帶寬總量(車道數量)限制總吞吐量上限;多個車道的馬路,bbr讓大家都能跑到馬路速度上限(不停留在網路設備buffer中),那車道數量限制總吞吐量。從而提高吞吐降低延遲。

原來的演算法在上下班高峰期的時候是大家都先嘗試往車道裡面慢慢擠進去,認慫了就停下來讓一讓,結果都堵到一起(buffer裡面),其實速度上來的路段都還空著呢,交警部門沒準對這種演算法很有興趣。


感覺BBR演算法對於有線網路場景下還是有很大提升的,但是在無線環境下,相較於cubic還是需要做些調整,感覺無線環境下丟包更嚴重,如果能很好的適配到無線環境下,應該很有意思


實測了一下
伺服器是google cloud engine在asia-east1-b機房(物理位置應該是在台灣)的VPS
伺服器端 debain 8,配置了ss
我自己這兒網路是電信100M ftth


未開啟bbr情況下

創建了一個快照克隆了一台vps做測試,開啟tcp bbr,明顯提升

當然,還是原先伺服器上開啟kcptun(參數fast)比較給力

考慮可以把bbr開起來,因為在家裡路由器里部署了kcptun,而在外面的話手機上沒法開kcptun,有時候看youtube確實比較卡


請教下,
1. bbr慢開始階段是如何結束的?因為結束時已經佔滿了buffer,是用出現大量丟包來判斷已經佔滿buffer,可以進入排空階段了嗎?

2. 對於帶寬增加的情況,bbr是如何做到每個周期可以更新估計帶寬的,是因為第一個rtt 增加1/4帶寬沒有引起rtt增加,所以認為估計帶寬可以刷新到當前帶寬的1.25倍么?


3. 對於帶寬減半的情況,bbr是如何識別出來的呢?我看文中說是當之前的帶寬估計超時(移出滑動窗口)之後,進行帶寬減半,這個超時具體怎麼判斷的?


我覺得防火牆會對不能識別的加密流量降速處理,就是故意丟包,tcp就一直等待對方回應,而不繼續發包,所以速度慢。bbr不管那麼多不等待對方回復繼續發包


並不是所有的主機用bbr都加速的,親測,所以還是要理論和實踐結合的


貼兩張開啟BBR的速度測試圖,Google Cloud台灣機房,成都電信……


第一名的回答已經非常好了, 使用 bbr 之後很大的一個優勢就是 tcp 帶寬可以提高很多, 我在國外的伺服器上搭建自己的 VPN, 啟用 bbr 之後可以很流暢的觀看 1080p 的 YouTube 視頻, 在沒有啟用 bbr 的時候, 1080p 的視頻根本就沒辦法流暢的觀看, 一卡一卡的. BBR 具體的安裝啟用過程可以看我的這篇 blog: Linux Tips: Ubuntu 安裝最新版本內核並啟用 TCP BBR


SS速度,1mbps→30mbps


改動郵件列表 tcp: BBR congestion control algorithm


很好的文章,很久也很少有對與TCP優化的文章了。這次google發表的也算是近期比較詳盡的文章,這對提升國內對TCP擁塞的關注是有好處的,相對其他提升速度的方式,TCP一直都是被忽視的,其實提升TCP的思路有很多。
不過,最好還是要實測,實際的效果確實有提升,比cubic演算法是要好,但沒有預期的提升的多,估計後面還是會有很長的優化,但確實是好東西。


我家的帶寬只有2M,BBR 可以讓我的網速更快么


推薦閱讀:

Google 自動駕駛/無人駕駛車用到哪些演算法?
如何看待谷歌在2017年IO大會上以小米和三星為例演示桌面圖標不匹配問題?
如何看待特斯拉自動駕駛的第一起命案?
谷歌收購了 Boston Dynamics,該公司的機器人在業界屬於什麼水平?
在移動設備上「搜索」的重要性和 PC 互聯網一樣高嗎?如果不是,為什麼?

TAG:Linux | 谷歌Google | TCP |