Google's BBR拥塞控制算法模型解析
1.首先,我對這次海馬臺風對深圳的影響非常準確,看過我朋友圈的都知道,沒看過的也沒必要知道,白賺了一天”在家辦公“是收益,但在家辦公著實效率不高,效果不好。
2.我為什么可以在周五的早上連發3篇博客,一方面為了彌補因為臺風造成”在家辦公“導致的時間蹉跎,另一方面,我覺的以最快的速度分享最新的東西,是一種精神,符合虔誠基督徒的信仰而不是道德約束。
3.上半年的時候,溫州皮鞋廠老板推薦了一個會議,大致是說”迄今為止的Linux進程調度器實現都是錯誤的...“,這讓我覺得可以寫一篇科普,但一直沒有動筆,這次BBR又讓我想起這件事。
??????? 由于本文是講BBR,所以關于調度器的內容,請自行閱讀《 THE LINUX SCHEDULER:A DECADE OF WASTED CORES》,關于這個方面的科普,我可能永遠都沒機會寫了,但是大家可以根據我推薦的東西自己去搜索,而且,我記得有一天我在班車上我曾經把這個推薦給我的同事了,不知道他是不是通過別的渠道分享了。
??????? 之前的幾篇關于TCP BBR擁塞控制算法的文章,我把精力和焦點放在了BBR的外圍以及實現本身,然而這兩者都說不是核心!我為什么這么說?海馬剛走,我以臺風為例。臺風外圍和臺風眼都是沒啥影響力的地帶,所以我說,一項技術,你僅僅知道它的外圍-比如它的背景,用法之類,或者僅僅知道它的實現-比如讀過/Debug過其源碼,或者二者兼得,都不是重要的,都沒啥影響力,技術的核心不在這里!所以,在介紹了BBR的背景和算法細節之后,我想簡單說一下其思路后面的模型,這是關鍵的關鍵。
??????? 既然涉及到了BBR的背后思想,我就把它奉為大寫了,不再bbr,而是BBR了!
??????? 本文的內容來自于對BBR算法個人理解的解說。圖片改自Yuchung Cheng和Neal Cardwell的 PPT,我增加了自己的理解。
0.模型
模型是最根本的!
我非常討厭把所有的東西雜糅在一起,我比較喜歡各個擊破,所以說,我最喜歡正交基!我希望把待觀測的東西分解成毫無耦合的N個方面,然后各自研究其特性。這個思路我曾經無數次提出,但是幾乎沒人會聽,因為一旦分解,你將看不到目標,看不到結果,拆了的東西并不定能再裝起來...令人欣慰的是,TCP的BBR算法思路也是這樣,不幸的是,TCP領域的頂級專家并沒有N維拆解,人家只是拆解了2個維度。
帶寬和RTT BandWidth & RTT我很驚奇Yuchung Cheng(鄭又中)和Neal Cardwell是怎么發現這個正交基的,為什么之前30年都沒有人發現這個,最為驚奇的是,他們竟然對了!他們的模型基于下圖展開:
這張圖幾乎完全描述了網絡的行為!這就是網絡傳輸的本質模型!之所以之前的Reno到CUBIC都是錯的,是因為它們沒有使用這個模型,我先來解釋一下這個模型,然后再看看將Reno/CUBIC套在這個模型上之后,是多么的荒唐。
??????? 值得注意的是,這個模型是Kleinrock & Gale早在1981年就提出來的,然而直到現在才被證明是有效的。之前的年月里,人們面臨著實現問題(同時測量問題,后面會講)。因此我把這個模型最終的實現者作為模型的主語,即Yuchung Cheng和Neal Cardwell們的模型,這并不是說他們是模型的發明者。就類似牛頓的定律一樣,其實伽利略已經提出了,只是沒有用數學系統的論證并總結而已。
1.有破才有立
首先,我們先要知道Reno/CUBIC錯在哪里,然后才能知道BBR是怎么改進的。??????? 骨子里,人們總希望時間成為橫軸,除了生命和做愛,人類幾乎所有的行為都是在于盡量縮短時間。
??????? 效率是什么?人們只知道效率的分母是時間!人們一旦把時間確定為橫軸,很多時候就會蒙蔽很多真相。這是一個哲學問題,我以后再談。
??????? 人們在為TCP建立性能模型的時候,總是用”序列號-時間曲線“,”序列號RTT曲線“等來觀察(比如Wireshark等分析工具),目標呢,很簡單,就是查一下”一個連接最快能突突多少數據“,
??????? 但是,這些都錯了!Why?
??????? 因為時間軸具有滯后性欺騙特征,所有基于時間軸的效率提升方案都是”先污染后治理“的方案!
??????? 看一下上面那個模型圖,所有30年來的擁塞控制算法的目標都是收斂于一個錯誤的收斂點(圖的右邊):不斷地增加數據的傳輸,試圖填滿整個網絡以及網絡上的所有緩存,以為這樣就會達到比較高的帶寬利用率,直到發現丟包,然后迅速降低數據發送量,之后重新向那個錯誤的收斂點前進,如此反復。這就是鋸齒的根源!這個現象在以上的模型圖上顯示的非常明確,根本就不用解釋。如果一開始人們就使用這個模型圖,任何人都不禁會問:為什么要一直在警戒區域徘徊呢?正確的收斂點不應該是暢通模式的最右端嗎??我以經典的VJ版TCP擁塞圖來說明一下:
??????? TCP與此不同,TCP的Reno/CUBIC并不是因為條件不具備才往緩存里屯數據包的,對于能搞出CUBIC那么復雜算法的人,搞定BBR根本就是小菜一碟,我承認我看不太懂CUBIC的那些算式背后的東西,但我對BBR的理解非常清晰,像我這種半吊子水平幾個月前就差一點實現了BBR類似的東西,但我絕對想不到CUBIC那么復雜的東西,之所以Reno/CUBIC被使用了30多年,完全是因為人們一直以為那是正確的做法,竟然沒有任何人覺得這種做法是有問題的。
??????? 基于{RTT,Delivery Rate}正交基的新模型一出來,人們好像猛然看到了事實的真相了:
問題的根源在于,BBR擁塞控制模型和BBR之前的擁塞控制模型對BDP的定義不同。BBR的模型中,BDP是不包括網絡緩存的,而之前的模型中,是包括緩存的,這就是說,包括緩存的擁塞控制模型中,擁塞控制本身和網絡緩存之間有了強耦合!要想做一個好的擁塞控制算法,就必須要徹底理解網絡緩存的行為,然而作為端到端的TCP協議,是不可能理解網絡緩存的。所以一直以來,30年以來都沒有出現一個比較好的算法,Reno到CUBIC,改進的只是算法本身,模型并沒有變!
??????? 網絡緩存是復雜的,有基于深隊列的緩存,也有基于淺隊列的緩存,不管怎樣,都會遇到 BufferBloat的問題,這是TCP所解決不了的,雖然如此,TCP還是嘗試填滿包括這些永遠琢磨不透的網絡緩存在內的BDP,這個填滿的過程是逐步的,開始于慢啟動,然后...這個逐步填滿BDP是兩個過程,首先是RTT不變,逐漸填滿不包括網絡緩存在內的管道空間(在我的定義中,這個屬于時間延展性的緩存空間),然后是逐漸填滿網絡緩存的過程(在我的定義中,這部分屬于不帶時間延展性的時間墻空間),問題處在TCP對后一個過程的不可知不可測的特性!!
??????? 既然知道了Reno/CUBIC的問題根源,那么BBR是怎么解決的呢?換句話說,BBR希望收斂在上圖中紅色圈圈的位置,它怎么做到的呢?
??????? 列舉做法之前,我先列舉一下{RTT,Delivery Rate}正交基的美妙:
??????? 最終,BBR的BDP如下圖所示,不再包括警戒區的網絡緩存:
2.BBR對最大帶寬和最小RTT的探測
從模型圖上可以清楚的看出如何探測最大帶寬:??????? 在這里首先要談一下BBR之前那些”基于時延“的擁塞控制算法。Reno/CUBIC屬于基于丟包的擁塞控制算法,而像Vegas之類的屬于基于時延的算法,其區別在于,Vegas對RTT的變化比較敏感,判斷擁塞的要素是RTT的變化而不是丟包,不管哪種算法,都需要外部發生一個事件,提示TCP連接已經處于擁塞狀態了。事實證明,Vegas之類的算法工作的并不好,原因在于它無法抵抗假擁塞,偶爾一次非擁塞造成的RTT增加也會引發TCP主動降窗,這種算法無法對抗共享深隊列的其它基于丟包的TCP連接的競爭,因此無法普遍被采用。
??????? BBR需要測量最小RTT,但是它是基于時延的擁塞算法嗎?
??????? 并不是!起初,當我第一次測BBR的時候,那是在國慶假期我醉酒后的第二天,幾乎動用了家里的所有設備(iMac一臺,Macbook Pro一臺,ThinkPad一臺,ROOT-Android平板一個,刷過的榮耀立方一個,樹莓派開發板一塊,ROOT-Android手機一個,極路由一個,iPhone兩個,iPad兩個...),搭建了一個測試網絡,讓BBR和CUBIC,Reno一起跑,并制造了RTT突變,發現BBR并沒有降速,甚至對RTT的突變不會有反應,而對RTT的變化的劇烈反應是基于時延的擁塞算法的基本特征,但BBR并沒有!任何組合情況下BBR都可以完爆其它算法。這是為什么?
??????? BBR在一個不隨時間滑動的大概10秒的時間窗口中采集最小RTT,BBR只使用這個最小RTT計算Pacing Rate和擁塞窗口。BBR不會對RTT變大進行反應。但是如果整的發生了擁塞,RTT確實會變大,BBR怎么發現這種情況呢?答案就在于這個時間窗口的超期滑動,如果在一個時間窗口內持續沒有采集到更小的RTT,那么就會將當前的RTT賦值個最小RTT。BBR就是這樣抵抗假擁塞的。秒級的窗口內,什么都是瞞不住的。這就是RTT的測量以及使用原則:
??????? 之前在網上看到一個美國硅谷工作的實習生質疑BBR會因為時延反應而不利于公平性,我本來想回復的,后來感覺翻次墻太麻煩了,
3.總結
我們一直需要的是一個”可持續發展“的方案來解決效率問題。不幸的是,TCP出現的30年來,我們見到的所有擁塞控制算法都是這種所謂的先污染后治理的方案,貫穿從Reno到CUBIC的所有算法。先把緩存填充到爆,然后再主動緩解,因為所有基于丟包的算法都在搶著填爆所有緩存,基于時延的算法太君子的主動降速行為就顯得競爭性不夠,典型的劣幣驅良幣的場景。??????? 我一直都以為TCP的加性增,乘性減是一個人人為我,我為人人的策略,確實,可以這么理解,然而這是一種敬人一杯,自罰一壺的策略,結局就是普遍倒下...
??????? 大家都能隨口說出ssthresh的作用是什么,比如當窗口大于它就怎么怎么樣,當小于它就如何什么的,但是有人知道它的含義嗎?也許,你會發現ss是slow start的縮寫,而thresh則是threshold的縮寫,門限的意思,但是這不是正確答案,正確的答案在 這里:
The capacity of a path can be informally defined by the sum of unused available bandwidth in the forward path and the size of buffers at bottleneck routers. ?
Typically, this capacity estimation is given by ssthresh.
真相如此晚近才被揭示,怪不得人們只知道ssthresh的用法而不知其含義啊!稍微詳細一點的東西也可以看我寫的一篇文章《 TCP核心概念-慢啟動,ssthresh,擁塞避免,公平性的真實含義》。
??????? 事實上ssthresh定義了路徑上所有緩存(包括時間延展緩存和時間墻緩存),所以說,當檢測到丟包時,會將cwnd減少1/2并賦值給ssthresh,此時因為BDP已經滿載,所以說其容量的1/2就是路徑的緩存容量!Perfect!然而這是錯的,TCP誤以為所有的緩存都是可以填充的,然而事實卻是,只有時間延展性質的緩存,即網絡本身才是可以填充的,而時間墻緩存卻是應急的緩存,所有的TCP只要都避免使用時間墻緩存(包括路由器,交換機上的隊列緩存),其才能真正起到應急的作用,帶寬利用率才會最大化!
??????? 應急車道是應急的,而不是行車的!
??????? BBR的新模型把這一切錯誤展示給了所有人,因此,BBR的指示是,保持最大帶寬,并最小化網絡緩存的利用。事實上,基于新模型額BBR要比之前的算法簡單多了!千萬不要覺得新算法一定很難,相反,BBR超級簡單。
??????? 也許你也已經想到了BBR類似的思路,但是它能夠在Linux上實現還是要對Linux的TCP實現動手術的,并不僅僅是一個擁塞模塊那么簡單,前幾天的文章說了N遍,BBR之前的擁塞控制算法在非Open狀態會被接管,再牛逼的算法也完全沒用,由于CUBIC試圖填滿整個包括隊列緩存在內的所有緩存空間,在當下的核心深隊列,邊緣淺隊列高速網絡環境中,只有不到40%的時間內TCP的擁塞狀態是處于Open狀態,大部分情況,傳統的算法根本就跑不到!好在BBR的實現中,作者注意到了這一點,完成了TCP擁塞控制的外科手術,快哉!
??????? BBR會在4.9或者5.0內核中成為默認的TCP擁塞控制算法嗎?我覺得可能還需要更多的測試,CUBIC雖然表現不佳,但起碼并沒有因為其表現帶來比較嚴重的問題,CUBIC的運行還是很穩定的。但是我個人希望,我希望BBR趕緊成為所有Linux版本的標配,徹底結束所謂TCP單邊加速這個丑行!
附:時間延展性緩存和時間墻緩存
我一直強調BBR是簡單的,是因為它確實簡單。因為在上半年的時候,我差一點就想出了類似的算法,當時我已經準備對PRR做手術了。??????? 我覺得擁塞控制算法對擁塞窗口的控制權不夠大,我希望用擁塞算法本身的邏輯來絕對窗口如何調整,而不是一味地PRR!我不相信檢測到三次重復ACK就一定是發生了丟包,即便是在非Open狀態,比如Recovery狀態,我也希望在我的算法認為可以的情況下可以增加窗口...我仔細分析了網絡的特征,總結除了兩類緩存:
帶有時間延展性的緩存,即網絡本身(確切的說是網線上跑的數據,從A到B需要時間,所以認為網絡是具有存儲功能的);
時間墻緩存,即路由器交換機的隊列緩存。這類緩存的性質就是內存。
關于這個,請參見我6月份寫的一篇文章《 TCP自時鐘/擁塞控制/帶寬利用之脈絡半景解析》,我在想,CUBIC算法到底要不要誘發TCP填充時間墻緩存,然而就CUBIC本身而言,區別這兩類緩存非常困難...我當時沒有一個好的模型,但我確實已經區別出了兩類緩存...
??????? 很遺憾,我沒有繼續下去,很多事情并不是我個人所能左右的,也不是我能安排的,不過當我看到BBR的那一刻,著實有一種找到答案的感覺。雖然,雖然很多事情不是我個人所能左右和安排,當我懼怕開始的時候,多數時候不知不覺中,默默地就結束了。你是不是也有這種感覺。
??????? 最后,那個哲學問題,聽著竇唯的老歌,我想可以談談了。效率的分母是時間的問題。
??????? 無論人們怎么努力,分母也不能是0!但有個例外,那就是一條蛇從尾巴開始吃掉自己的情形!你能想象那種場景嗎?除非可以沿著時間軸任意穿越,否則這就是不可能的,是這樣嗎?我覺得這種事沒那么復雜,只要上升一個維度去考慮就好了,任何低一級的維度里任何東西對于高一級維度而言就是一個點,也就是一個小宇宙。一條蛇是一個三維動物,它永遠也意識不到四維時空里面的一個點,就是它自己吃掉的自己。爆炸!
總結
以上是生活随笔為你收集整理的Google's BBR拥塞控制算法模型解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cmd 切换目录
- 下一篇: Python3中的GBK、UTF-8和U