TCP擁塞控制算法的目的可以簡單概括為:公平競爭、充分利用網絡帶寬、降低網絡延時、優化用戶體驗,然而就目前而言要實現這些目標就難免有權衡和取舍。
算法分類
基于丟包策略的傳統擁塞控制算法的幾個迭代版本,如圖所示:
與此同時還有一類算法是基于RTT延時策略來進行控制的,但是這類算法在發包速率上可能不夠激進,競爭性能不如其他算法,因此在共享網絡帶寬時有失公平性,但是算法速率曲線卻是很平滑
基于鏈路容量的擁塞控制:實時測量網絡帶寬和時延,認為網絡上報文總量大于帶寬時延乘積時出現了擁塞,如 BBR。
基于學習的擁塞控制:沒有特定的擁塞信號,而是借助評價函數,基于訓練數據,使用機器學習的方法形成一個控制策略,如 Remy。
如何感知擁塞
基于各種擁塞策略的擁塞控制算法有不一樣的擁塞判斷標準:
-
基于丟包
丟包可以由重傳超時
RTO
和重復確認來做判斷。丟包判斷 基于時延
基于鏈路容量
-
基于機器學習
根據參數得出一個擁塞窗口值
擁塞控制基本策略
擁塞控制是一個動態的過程,它既要提高帶寬利用率發送盡量多的數據又要避免網絡擁堵丟包RTT增大等問題,基于這種高要求并不是單一策略可以搞定的,因此TCP的 擁塞控制策略實際上是分階段分策略的綜合過程:
基于丟包的擁塞控制
Tahoe算法
如果收到三次重復確認即第四次收到相同確認號的分段確認,并且分段對應包無負載分段和無改變接收窗口的話,Tahoe算法則進入快速重傳,將慢啟動閾值改為當前擁塞窗口的一半,將擁塞窗口降為1個MSS,并重新進入慢啟動階段。
擁塞控制過程大致如下:
Reno算法(我們當前理解的算法)
如果收到三次重復確認,Reno算法則進入快速重傳只將擁塞窗口減半來跳過慢啟動階段,將慢啟動閾值設為當前新的擁塞窗口值,進入一個稱為快速恢復的新設計階段。
擁塞控制流程如下:
Reno 算法將收到 ACK 這一信號作為擁塞窗口增長的依據,在早期低帶寬、低時延的網絡中能夠很好的發揮作用,但是隨著網絡帶寬和延時的增加,Reno 的缺點就漸漸體現出來了,發送端從發送報文到收到 ACK 經歷一個 RTT,在高帶寬延時(High Bandwidth-Delay Product,BDP)網絡中,RTT 很大,導致擁塞窗口增長很慢,傳輸速度需要經過很長時間才能達到最大帶寬,導致帶寬利用率將低。
適用場景:
適用于低延時、低帶寬的網絡。
TCP New Reno是對TCP Reno中快速恢復階段的重傳進行改善的一種改進算法,New Reno在低錯誤率時運行效率和選擇確認SACK相當,在高錯誤率仍優于Reno。
CUBIC算法
Cubic是 Linux 內核 2.6 之后的默認 TCP 擁塞控制算法, 使用一個立方函數(cubic function):
作為擁塞窗口的增長函數,其中,C 是調節因子,t 是從上一次縮小擁塞窗口經過的時間,是上一次發生擁塞時的窗口大小,
β是乘法減小因子。從函數中可以看出擁塞窗口的增長不再與 RTT 有關,而僅僅取決上次發生擁塞時的最大窗口和距離上次發生擁塞的時間間隔值。
Cubic 擁塞窗口增長曲線如下,凸曲線部分為穩定增長階段,凹曲線部分為最大帶寬探測階段。如圖下圖 所示,在剛開始時,擁塞窗口增長很快,在接近 口時,增長速度變的平緩,避免流量突增而導致丟包;在
附近,擁塞窗口不再增加;之后開始緩慢地探測網絡最大吞吐量,保證穩定性(在
附近容易出現擁塞),在遠離
后,增大窗口增長的速度,保證了帶寬的利用率。
當出現丟包時,將擁塞窗口進行乘法減小(擁塞窗口減小到當前的一半),再繼續開始上述增長過程。此方式可以使得擁塞窗口一直維持在 附近,從而保證了帶寬的利用率。Cubic 的擁塞控制過程:
Cubic 算法的優點在于只要沒有出現丟包,就不會主動降低自己的發送速度,可以最大程度的利用網絡剩余帶寬,提高吞吐量,在高帶寬、低丟包率的網絡中可以發揮較好的性能。
但是,Cubic 同之前的擁塞控制算法一樣,無法區分擁塞丟包和傳輸錯誤丟包,只要發現丟包,就會減小擁塞窗口,降低發送速率,而事實上傳輸錯誤丟包時網絡不一定發生了擁塞,但是傳輸錯誤丟包的概率很低,所以對 Cubic 算法的性能影響不是很大。
Cubic 算法的另一個不足之處是過于激進,在沒有出現丟包時會不停地增加擁塞窗口的大小,向網絡注入流量,將網絡設備的緩沖區填滿,出現 Bufferbloat
(緩沖區膨脹)。由于緩沖區長期趨于飽和狀態,新進入網絡的的數據包會在緩沖區里排隊,增加無謂的排隊時延,緩沖區越大,時延就越高。另外 Cubic 算法在高帶寬利用率的同時依然在增加擁塞窗口,間接增加了丟包率,造成網絡抖動加劇。
適用場景:
適用于高帶寬、低丟包率網絡,能夠有效利用帶寬。
基于鏈路容量的算法
BRR算法
BBR[4] 是谷歌在 2016 年提出的一種新的擁塞控制算法,已經在 Youtube 服務器和谷歌跨數據中心廣域網上部署,據 Youtube 官方數據稱,部署 BBR 后,在全球范圍內訪問 Youtube 的延遲降低了 53%,在時延較高的發展中國家,延遲降低了 80%。目前 BBR 已經集成到 Linux 4.9 以上版本的內核中。
BBR 算法不將出現丟包或時延增加作為擁塞的信號,而是認為當網絡上的數據包總量大于瓶頸鏈路帶寬和時延的乘積時才出現了擁塞。
BBR 算法周期性地探測網絡的容量,交替測量一段時間內的帶寬極大值和時延極小值,將其乘積作為作為擁塞窗口大小(交替測量的原因是極大帶寬和極小時延不可能同時得到,帶寬極大時網絡被填滿造成排隊,時延必然極大,時延極小時需要數據包不被排隊直接轉發,帶寬必然極小),使得擁塞窗口始的值始終與網絡的容量保持一致。
什么叫做BDP
呢?它叫做帶寬時延積,例如一條鏈路的帶寬是100Mbps
,而RTT是40ms
,那么
BDP=100Mbps*0.04s=4Mb=0.5MB
即平均每秒飛行中的報文應當是0.5MB。因此Linux的接收窗口緩存常參考此設置:
事實上,我們的傳輸速度在3個階段被不同的因素限制:
- 應用程序限制階段,此時RTT不變,隨著應用程序開始發送大文件,速率直線上升;
- BDP限制階段,此時RTT開始不斷上升,但吞吐量不變,因為此時瓶頸路由器已經達到上限,緩沖隊列正在不斷增加;
- 瓶頸路由器緩沖隊列限制階段,此時開始大量丟包。
如下所示:
如CUBIC這樣基于丟包的擁塞控制算法在第2條灰色豎線發生作用,這已經太晚了,更好的作用點是BDP上限開始發揮作用時,也就是第1條灰色豎線。
而BBR通過檢測RTprop
和BtlBw來實現擁塞控制。什么是RTprop
呢?這是鏈路的物理時延,因為RTT里含有報文在路由器隊列里的排隊時間、ACK的延遲確認時間等。什么叫延遲確認呢?TCP每個報文必須被確認,確認動作是通過接收端發送ACK報文實現的,但由于TCP和IP頭部有40個字節,如果不攜帶數據只為發送ACK網絡效率過低,所以會讓獨立的ACK報文等一等,看看有沒有數據發的時候順便帶給對方,或者等等看多個ACK一起發。所以,可以用下列公式表示RTT與RTprop
的差別:
RTT我們可以測量得出,
RTprop
呢,我們只需要找到瓶頸路由器隊列為空時多次RTT測量的最小值即可
而BtlBw
全稱是bottleneck bandwith,即瓶頸帶寬,我們可以通過測量已發送但未ACK確認的飛行中字節除以飛行時間deliveryRate
來測量
早在1979年Leonard Kleinrock就提出了第1條豎線是最好的擁塞控制點,但被Jeffrey M. Jaffe證明不可能實現,因為沒有辦法判斷RTT變化到底是不是因為鏈路變化了,從而不同的設備瓶頸導致的,還是瓶頸路由器上的其他TCP連接的流量發生了大的變化。但我們有了RTprop和BtlBw后,當RTprop升高時我們便得到了BtlBw,這便找到第1條灰色豎線最好的擁塞控制點,也有了后續發送速率的依據。
由于 BBR 的擁塞窗口是精確測量出來的,不會無限的增加擁塞窗口,也就不會將網絡設備的緩沖區填滿,避免了出現 Bufferbloat
(緩沖區膨脹)問題,使得時延大大降低。
如下圖所示,網絡緩沖區被填滿時時延為 250ms
,Cubic 算法會繼續增加擁塞窗口,使得時延持續增加到 500ms
并出現丟包,整個過程 Cubic 一直處于高時延狀態,而 BBR 由于不會填滿網絡緩沖區,時延一直處于較低狀態。
由于 BBR 算法不將丟包作為擁塞信號,所以在丟包率較高的網絡中,BBR 依然有極高的吞吐量,如圖 5下圖所示,在 1% 丟包率的網絡環境下,Cubic 的吞吐量已經降低 90% 以上,而 BBR 的吞吐量幾乎沒有受到影響,當丟包率大于 15% 時,BBR 的吞吐量才大幅下降。
BBR 算法是反饋驅動的,有自主調節機制,不受 TCP 擁塞控制狀態機的控制,通過測量網絡容量來調整擁塞窗口,發送速率由自己掌控,而傳統的擁塞控制算法只負責計算擁塞窗口,而不管發送速率(pacing rate),怎么發由 TCP 自己決定,這樣會在瓶頸帶寬附近因發送速率的激增導致數據包排隊或出現丟包。
經過測試,在高延時、高丟包率的環境下,BBR 相對于 Cubic 算法在傳輸速度上有較大的提升,具體的測試結果如下表所示:
BBR 算法的不足之處在于設備隊列緩存較大時,BBR 可能會競爭不過 Cubic 等比較激進算法,原因是 BBR 不主動去占據隊列緩存,如果 Cubic 的流量長期占據隊列緩存,會使得 BBR 在多個周期內測量的極小 RTT 增大,進而使 BBR 的帶寬減小。
適用場景:
適用于高帶寬、高時延、有一定丟包率的長肥網絡,可以有效降低傳輸時延,并保證較高的吞吐量。
基于學習的算法
Remy
Remy 也稱為計算機生成的擁塞控制算法(computer-generated congestion-control algorithm),采用機器學習的方式生成擁塞控制算法模型。
略了吧......??
基于時延的算法
Vegas算法
Vegas將時延 RTT 的增加作為網絡出現擁塞的信號,RTT 增加,擁塞窗口減小,RTT 減小,擁塞窗口增加。具體來說,Vegas 通過比較實際吞吐量和期望吞吐量來調節擁塞窗口的大小.
期望吞吐量為:
實際吞吐量為:
定義一個它們之間的差距diff
:
BaseRTT
是所有觀測來回響應時間的最小值,一般是建立連接后所發的第一個數據包的 RTT,cwnd
是目前的擁塞窗口的大小。Vegas 定義了兩個閾值 a,b,當 diff > b 時,擁塞窗口減小,當 a <= diff <=b 時,擁塞窗口不變,當 diff < a 時,擁塞窗口增加。
Vegas 算法采用 RTT 的改變來判斷網絡的可用帶寬,能精確地測量網絡的可用帶寬,效率比較好。但是,網絡中 Vegas 與其它算法共存的情況下,基于丟包的擁塞控制算法會嘗試填滿網絡中的緩沖區,導致 Vegas 計算的 RTT 增大,進而降低擁塞窗口,使得傳輸速度越來越慢,因此 Vegas 未能在 Internet 上普遍采用。
適用場景:
適用于網絡中只存在 Vegas 一種擁塞控制算法,競爭公平的情況。
歡迎dajia訂閱我的博客??:hugo.jiahongw.com
參考: