深入理解TCP擁塞控制——從BIC到CUBIC

引言

       網上的各種博文一提到tcp的擁塞控制,都是清一水的慢啓動,擁塞避免,快速重傳,呃...雖然沒什麼問題,但是這都9012年了,tcp的擁塞控制算法已經演變了很多了,在linux內核2.6.8中,就默認採用BIC擁塞控制算法了,在2.6.18中,默認的擁塞控制算法採用了CUBIC,網上各種講CUBIC的不算太多,個人覺得這篇博文講的還不錯,但該文偏向於從宏觀和趨勢的角度去理解CUBIC,對於某些細節就少了一些說明,而且雖然那篇博文雖說是簡化了公式推導,但我感覺他把公式理解的太複雜化了,因此,纔有了本文,本文的目的在於幫大家更細節化的瞭解BIC和CUBIC的由來及細節,同時簡化大家對CUBIC的公式理解。OK,下面開始我們的正文。

BIC誕生的緣由

       任何事物的產生與興起一定有他的緣由,爲什麼誕生了BIC,又誕生了CUBIC?一定是tcp_reno有他不好用的地方,我們來回憶一下reno的擁塞控制流程,也就是大家熟悉的慢啓動,擁塞避免,快速重傳,盜用一張經典的圖:

                             

       我們知道,在reno版本的擁塞控制下,進入擁塞避免狀態或快速恢復狀態後,每經過一個RTT纔會將窗口大小加1,那麼問題來了,假設我們鏈路狀況好,但如果RTT很長的話,reno不就要很長時間才能達到最佳擁塞窗口了嗎?知道了這一點,你也就知道了爲什麼會產生tcp_BIC,BIC(Binary Increase Congestion control) 的中文名我也不清楚該怎麼叫,但我建議大家理解成二分搜索擁塞控制算法,爲什麼這麼說呢?因爲BIC的核心思想就是通過二分搜索的思想來找到當前鏈路最合適的擁塞窗口,下面我們來詳細闡述下BIC算法的主要流程。

BIC算法流程

       顯然,當前鏈路在網絡上因爲排隊而發生丟包時,鏈路的當前最佳擁塞窗口肯定是小於丟包時的擁塞窗口的,我們稱丟包時的擁塞窗口大小爲Wmax,同樣,BIC也採用乘法減小的方式減小窗口,我們稱這個因子爲\beta,同時,我們稱減小後的窗口爲Wmin,則有Wmin=\beta*Wmax,我們認爲乘法減小後的窗口應該是小於最佳擁塞窗口的,因此,對於鏈路當前最佳擁塞窗口W來說,我們有Wmin<W<Wmax,reno採用加法去搜索W的方式實在是太慢了,因此BIC採用了二分搜索的方式去找到這個W,二分搜索的具體流程就不贅述了,我們來看看這麼做的好處,首先我們來看下BIC的擁塞窗口圖像:

                                                

       我們看虛線左邊的圖像,也就是加法增窗(Additive Increase),二分搜索(Binary Search)的過程,整個增窗流程趨近一個凸函數的左半邊,這樣帶來的好處是:越接近Wmax附近,窗口的增加速度越慢,這也就意味着,在一次經歷了一次丟包後,窗口會更快的接近W,並在W附近停留更多的時間(對比reno的鋸齒形圖像可以有更明顯的感覺)。當然你可能會覺得,W如果在Wmin附近呢?不是更快超過了嗎?如果你產生了這樣的疑問,你需要明確一個觀點,對於整個網絡來說,我們需要的是最終的收斂,而不是一次的收斂,網絡擁塞丟包的大部分情況是,當前網絡中所有的連接佔滿了帶寬,此時有一個新鏈路加進來,那麼新鏈路爭搶資源過程則勢必會引起丟包,合適的做法應當是,現有的各條鏈路讓出部分資源,讓新的鏈路可以和舊鏈路一樣公平的拿到其應得的資源。所以,我們需要的是最終收斂,所有鏈路快速公平的拿到帶寬資源,因此,我們衡量一個擁塞控制算法的優劣時,會看他的收斂速度,公平性。回到剛纔的問題上來,W如果在Wmin附近也並不影響,BIC會快速進入到下一次增窗過程中去,然後達到最終收斂。

       再來看虛線右邊的圖像,這個過程被稱作最大窗探測過程(Max Probing),顧名思義,這個過程就是在探測當前合適的最大窗口,爲什麼要設計成這樣呢?BIC算法的設計者認爲,當窗口Wmax超過以後,如果還未發生丟包,則說明網絡變好了,或者有部分鏈接讓出了資源,那麼我們要儘可能的去搶佔他,首先我們先慢慢的嘗試,然後越來越快,以保證整個網絡資源的利用率,因此Max Probing被設計爲虛線左邊的旋轉對稱的模樣。當然,Max Probing的增窗過程真的合理嗎?它確實保證了快速收斂,但對於其公平性(相對於tcp_reno,網絡上會同時存在大量擁塞算法),可能要打一個問號。

       關於BIC,這裏再說一些細節上的東西,出於工程實現和現實應用的考慮,在窗口調整過程中設置了一個SmaxSmin的閾值,當窗口的增量大於時,增量則設爲,當窗口增量爲時,則將當前窗口設爲Wmax,也就是說窗口已經通過二分搜索達到了最大值,可以開始Max Probing階段了,具體原因很好理解,不贅述了。

CUBIC誕生的緣由

       從感覺上來說,BIC在long fast的網絡場景下表現的已經很好了,爲什麼又產生了CUBIC呢?首先,如果你設計了一個新東西,你肯定希望能把他應用的更廣泛,那麼BIC能不能用到RTT較小,丟包較高的環境中呢?我們知道tcp_reno已經廣泛的應用在了網絡中,同時還有HSTCP,tcp_WestWood,tcp_vegas等,一個新協議的出現不可能馬上替換掉所有舊的,而根據我們前面的分析,BIC在離Wmax較遠時,窗口增速很快,如果將BIC廣泛應用到RTT較小,丟包較高的網絡中去,BIC的增窗策略太激進了,大量的搶佔了資源,公平性實在是難以保證。同時,BIC的二分搜索增窗,Max Probing的指數增窗,SmaxSmin的限定,實現相對複雜(呃...好吧,相對CUBIC確實複雜很多),同時也很難以對性能進行分析,於是,誕生了我們的CUBIC。CUBIC的名字很有意思,cubic本來就是立方的意思,而又可以理解成cu-bic,也就是cubic-BIC的樣式,感覺上就有點GNU取名的味道。從名字上我們知道CUBIC是跟立方有關的,下面我們來詳細介紹CUBIC的整體流程。

CUBIC算法流程

       知道了BIC的存在的問題,也就知道了CUBIC的核心思想,CUBIC解決問題的思路很巧妙,既要BIC的高效,又要公平性,要實現BIC的高效只需要窗口調整過程的圖像類似BIC即可,任意一個奇數階的多項式圖像均可以擬合BIC的圖像,對於公平性而言,既然reno和BIC都以RTT爲單位爭搶資源,那麼爲什麼不能把窗口的調整過程從以RTT爲單位的思路獨立出來呢?這樣就可以通過調整時間的步長來維持公平性。CUBIC通過這個公式給出瞭解決方案:

                                                           

       關於K的推導是一個很簡單的方式,我們先來看這個函數的圖像:

                                                  

       CUBIC和BIC是類似的,同樣也是乘法減小的過程,那麼也就意味着t=0時刻,窗口是我們的Wmin,也就是\beta*Wmax,把t=0W(0)=\beta*Wmax帶入,解出來

                                                             

       這也就爲什麼我在開篇說的那篇博文中對於K的解釋太繁瑣了,講到這裏,其實CUBIC的核心也差不多講完了,CUBIC將BIC的二分搜索過程和Max Probing以公式的形式獨立出來,剝離了其對RTT的依賴,同時這也大量減輕了代碼負擔,一個公式就全部搞定了。再說一點CUBIC的細節吧,CUBIC可以通過調整C和\beta來調整窗口調整速度,來保證公平性和性能的協調(關於C和\beta這一塊的取值證明大家可以自己搜論文看看,不得不說很多東西有公式量化就很方便分析了)。然而在實際應用中,CUBIC發現在有些時刻還是有點搶不過reno,因此CUBIC還增加了一些細節策略,比如:在一次丟包事件後,經過t時間,如果CUBIC的增窗速度小於標準TCP,則,採用標準TCP增加的窗口大小。

       好吧,文章的最後我們來看看CUBIC的公平性以及在long fast網絡中的性能優勢:

       本文的數據以及某些思路來源於這篇論文:CUBIC: A New TCPFriendly HighSpeed TCP Variant

       有興趣的朋友可以自行翻牆下載。

 

       

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章