TCP BBR算法的帶寬敏感性以及高丟包率下的優化

bbr算法比較簡單也比較容易理解,全部關於它的優化也就一樣不復雜了。
        請注意,任何優化都只針對特定場景的,根本不存在一種聽任四海而皆準的算法。咱們分析Google的測試報告時,比較容易被忽視的是其bbr算法的部署場景。若是能夠完美復現Google的B4網絡,那麼測試結果應該就跟Google是一致的,但不得不說,bbr算法內置了不少的參數(目前的版本中是寫死的),Google方面有沒有調整這些參數是未知的。咱們先看一下bbr算法是怎麼利用空餘帶寬的。
        bbr算法最終會穩定在Steady-state,即其PROBE_BW的狀態,該狀態內置了一個小循環,bbr在這個循環中不停運轉:算法

 

 

注意其中的速率增益:1|1|1|1|1|1|1.25|0.75|1|1|1|1|1|1|1.25|0.75|1|...這個循環增益徹底是bbr自主的循環增益,不受任何外界控制,是否進入下一個增益取決於如下的判斷:
1.正增益週期,是否在不丟包狀況下已經填滿了可用帶寬,這個旨在提升資源利用率(效率因素);
2.減損週期內,是否已經騰出了部分能夠資源,這個旨在知足公平性(公平因素);
3.平穩反饋週期是否足夠久,使得共享資源的TCP鏈接有時間收斂到一個公平的位置(公平因素)。

這是個典型的效率優先兼顧公平的實例,可是咱們能夠看到,若是上述的第三點,即平穩反饋週期過久會怎樣?很顯然,這樣的話會下降bbr的搶佔性和靈活性,bbr發現帶寬富餘的最短期就是6個RTT,這對於某些場景而言顯然是不足的。所以,咱們能夠得出第一個結論:
PROBE_BW狀態中平穩反饋週期的長度決定了bbr搶佔敏感性。
一個最簡單且極端的例子,若是咱們將bbr在PROBE_BW的pacing gain數組改爲下面這個樣子,其將會第一時間發現帶寬富餘,然則代價就是發送速率的顛簸,這對下載業務是好的,可是並不利於直播點播業務:數組

// 將8個元素的數組改爲2個元素的數組,是的bbr在Steady-state處於顛簸徘徊狀態。  
static const int bbr_pacing_gain[2] = {  
    BBR_UNIT * 5 / 4,    /* probe for more available bw 油門*/  
    BBR_UNIT * 3 / 4,    /* drain queue and/or yield bw to other flows 剎車*/  
//    BBR_UNIT, BBR_UNIT, BBR_UNIT,    /* cruise at 1.0*bw to utilize pipe, */  
//    BBR_UNIT, BBR_UNIT, BBR_UNIT    /* without creating excess queue... */  
};

 

這個比較相似與那些有事沒事鳴着喇叭的110車,無論路上多麼堵,它們一遍遍拿着喇叭喊着」靠邊!靠邊!「,老是能過得去,估計司機也是一腳油門一腳剎車踩的很辛苦(我並無說120和119,那是由於120和119沒事的話不敢這麼玩,醫生和消防武警仍是牛不過警察的)。
        接下來咱們來看第二個話題,那就是bbr的崖點在哪?
        咱們知道,Reno/CUBIC直接在膝點出採起措施,使得擁塞得以免,即使是持續保持慢速,也不會到達崖點,Reno/CUBIC將丟包做爲到達膝點的標誌,而後退出擁塞控制算法,進入擁塞恢復階段,直到擁塞被認爲緩解恢復正常,是不會把控制權再度交給擁塞控制算法的。這也是經典的擁塞控制風格做風,本質就是在膝點採起措施,避免從崖點跌落,這即是經典的鋸齒之由來!鋸齒尖的位置,那是膝點,而不是崖點!
        那麼bbr是否是也相似呢?非也!由於bbr不會被接管,bbr本身全程負責全部的擁塞處理!事實上,bbr根本無論什麼擁塞不擁塞,它只是單純的根據本身收到的帶寬反饋來計算下面發送的帶寬,即使真的發生了擁塞,不也仍是能夠發送數據的麼,只是發送的多是重傳數據而不是新數據而已。
        咱們來看一張來自Google的bbr測試結果圖示:緩存

 

 

問題我已經標在上面了,爲何bbr會面臨一個崖點,此後徹底不可恢復!雖然CUBIC最終也是歸於同一結局,可是它是按比例滑落的,而不像bbr那樣跌落通常。這個怎麼解釋呢?這個問題有同事和罈子裏的都問過我,但我並無給出正面回答,由於我以爲咱們本身很難模擬真實的丟包環境。第一,咱們沒有模擬任意丟包率的獨立儀器(丟包不受TCP發送量的影響,就算只發一個包,該丟也得丟),咱們所謂的丟包幾乎都是因爲咱們本身形成的,是咱們本身的TCP形成的,其次,能認識到第一點事實的人不多,明白現有Linux TCP擁塞狀態機邏輯和擁塞控制算法邏輯關係的人更少。這樣一來若是測出的結果沒有發現崖點,那即是無休止的毫無心義的爭論。無神論者永遠都只能是個什麼什麼者,那只是它們本身相信沒有神,讓他們去說服基督徒,那是會被打死的,雖然,基督徒也不能證實有神!
        因此,我通常而言會盡力避開這種爭論,不管任何方面,即使我知道的再多,我也會爭取作一名沉默的人。
        我直接給出答案吧,崖點的存在,正是由於bbr_pacing_gain數組的固定配置。
        崖點的存在是一種」資不抵債「的退避措施!咱們看到在bbr_pacing_gain數組中,其增益元素的增益比是1/4,也就是25%,能夠簡單理解爲,在增益週期,bbr能夠多發送25%的數據!
        注意看上面的圖的橫軸丟包率,當丟包率接近25%的時候,曲線從崖點跌落,這並非偶然的!過程很容易理解,首先,在增益期,x%的丟包率是否抵消了增益比25%?也就是說,x是否大於25。
        咱們假設x就是25!那麼可想而知,25%的收益徹底被25%的丟包所抵消,至關於沒有收益,接下來的減損週期,又減小了25%的發送數據,同時丟包率依然是25%...再接下來的6個RTT,持續保持25%的丟包率,而發送率卻僅僅基於反饋,即每次遞減25%,咱們能夠看到,在bbr_pacing_gain標識的全部8週期,數據的發送量是隻減不增的,而且會一直持續下去,這就是崖點!
        以上個人假設是x就是25,事實上,丟包率在不足25%的時候,以上的減損現象就已經開始呈現了,在Google的測試中,咱們發現從5%的丟包率開始,持續到10%左右的丟包率,而後到15%~20%丟包率的時候,吞吐率持續下跌,一直跌到底。咱們能夠看到,在bbr_pacing_gain數組中,除了bbr_pacing_gain[0]表示增益以外,在有丟包的狀況下,其它的都是減損,特別在高丟包率(我一貫以爲5%以上就是很高丟包率了)下更是明顯。
        好了,咱們把上述的論述總結在一個圖示上:網絡

 

 

而後咱們獲得的新結論是:
1.bbr_pacing_gain數組的bbr_pacing_gain[0]係數(當前是5/4),決定了抗丟包能力;
2.bbr_pacing_gain數組中係數爲1(即平穩反饋週期)的元素的多少,決定了抗丟包能力(過久,則會持續衰減,過短,則比較顛簸)。

咱們從Google的bbr部署說明裏也能夠看出:
CUBIC’s loss tolerance is a structural property of the algorithm, while BBR’s is a configuration parameter.
As BBR’s loss rate approaches the ProbeBW peak gain, the probability of measuring a delivery rate of the true BtlBw
drops sharply, causing the max filter to underestimate.

其中爲何會」causing the max filter to underestimate「呢?由於max filter是基於時間窗口的,隨着時間的流逝,bbr會忘掉以前的大帶寬,只記着如今因爲丟包持續減小的小帶寬。你要注意,其實只要有丟包,在6個平穩反饋週期內,帶寬就是持續減小的,然而,問題是,這些減小的量能不能經過增益週期,即bbr_pacing_gain[0]的收益一次性補償,若是不能,那麼跌入崖點就是必然的。
        所以,拿什麼來抵抗丟包呢?答案是損失一點公平性,用增益係數去換!我把5/4換成了3/2,效果良好,大概到丟包率30%之後才跌入崖點,要知道30%的丟包率,可用性幾乎已經能夠說是零了!另外,我爲何不減小bbr_pacing_gain數組中增益係數爲1的元素的數量呢?由於這會嚴重影響公平性!因此我保持其8個元素。
        這是bbr不如CUBIC的地方,bbr事實上徹底基於反饋,正常來說按照VJ的數據守恆規則,一個包離開另外一個方可進入的狀況下,丟包率自己就會持續拉低帶寬,bbr有一個5/4的增益,這可能會彌補丟包帶來的反饋減損,然而增益係數5/4倒是一個配置參數,當丟包率大於25%的時候,就會資不抵債!甚至丟包率在10%~15%的時候,bbr的表現就開始不佳。所以,若是能動態計算丟包率,而後將丟包率反饋給增益係數,動態計算增益係數,我想效果應該會不錯。好比丟包率達到25%的時候,增益係數就變成50%,這樣就能夠避免因爲丟包帶來的反饋減損,然而,你又如何判斷這些丟包是噪聲丟包仍是擁塞丟包呢?答案在於RTT!只要時間窗口內的RTT不增長,那麼丟包就不是擁塞致使的,感謝Gail & Kleinrock給出的模型,感謝Yuchung Cheng & Neal Cardwell證實了這是對的。
        順便說一句,因爲CUBIC的表現就是填滿全部能夠填滿的緩存,它們的行爲是可怕的,要不是CUBIC還遵循着乘性減窗(只是減到了原來的0.7而不是0.5),網絡估計早就崩潰了,即使如此,若是不是由於大量的TCP接收端限制了接收窗口,網絡也是要被CUBIC搞崩潰的。現現在,有將近30%~50%的接收端通告了一個比CUBIC計算出來的更小的窗口,感謝這些接收端,使得咱們免受CUBIC Flood的危害!app

相關文章
相關標籤/搜索