網絡協議基礎(三):TCP擁塞控制算法

TCP的幾個重要的特性可以簡單的表述爲不丟包、不亂序、流量控制、擁塞控制。前三者其實在上一篇文章《TCP報文頭部詳解》講解頭部20字節加選項時已經具體介紹過了,並且擴展講述瞭如何避免發送過多的小包問題,本節着重於研究我靠記憶而沒有深入去理解的幾個擁塞控制算法。

1.瞭解擁塞控制歷史

  • 以丟包爲依據
    應用於Linux2.6.19的CUBIC(RFC8312)算法是目前基於丟包爲依據進行擁塞控制的主要方式
  • 以探測帶寬作爲依據
    最知名的就是BBR(應用於Linux4.9)算法

2.慢啓動

  • 瞭解擁塞窗口cwnd(congestion window)
  • 通告窗口rwnd(receiver‘s advertised window)
    實際發送窗口swnd = min(cwnd,rwnd)

通過正常的網課學習,其實都明白在慢啓動階段擁塞窗口呈現指數型增長,那麼試問慢啓動初始窗口 IW(Initial Window)是怎樣設計的哩?簡單來說從設計的初始階段爲1*MSS,經過3*MSS,現在大多采用10*MSS.

3.擁塞避免

先認識一個背誦擁塞控制相關知識點時經常見到的名詞ssthresh(slow start threshold),即慢啓動閾值,當慢啓動的擁塞窗口達到ssthresh時就會進入擁塞避免階段,接下來就以一個具體的例子,看一看慢啓動與擁塞避免的轉化以及ssthresh的變遷。

在這裏插入圖片描述如上圖所示在慢啓動初始階段,cwnd以指數性增長的方式增長,當達到ssthresh時進入擁塞避免階段,其cwnd的增長規律見圖中公式,之後當發生丟包時調整ssthresh爲cwnd/2,並且重新設置cwnd開始慢重傳的,慢恢復的過程。

4.快速重傳與快速恢復

首先了解失序數據段,因爲TCP會默認在內核緩衝區按序響應ACK報文,若報文丟失,將會產生連續的失序 ACK 段。除此之外, 若網絡路徑與設備導致數據段失序或者報文重複,也將會產生少量的失序 ACK 段。把這幾種情況下的報文叫做失序數據段,而擁塞控制其實就是爲了解決包丟失的問題,慢重傳解決超時報文,快重傳解決失序數據段的問題。

既然由上面以及瞭解了快重傳的應用場景與具體舉措,如下圖所示展示了快速重傳與快速恢復的具體過程:
快重傳
恰如上圖所示,在收到連續三個失序數據段的Ack之後發送方並不會等到RTO(超時定時器定時)到達,而是會立刻發送丟失的數據報。接收端在接收到填充失序缺口的數據段時,立刻發送它所期待的下一個 ACK 序列號,如上圖所示收到丟失的包5之後,由於包7、8以及到達了,所以直接回Ack9即可 。在RFC2581文檔中定義的快重傳方式是將 ssthresh 設置爲當前擁塞窗口 cwnd 的一半,設當前 cwnd 爲 ssthresh 加上 3*MSS 。
然而存在的一個問題是,應該如何發送丟失的報文?因爲發送方並不能確認丟失報文之後已發送的報文(如圖中7,8)接收端是否已經收到,所以需要發送方選擇一合適的方法來確認是只發送丟失的報文還是以後的報文也重新發送?

5.SACK與選擇性重傳算法

在第4節末尾,提出了一個疑問,我們常採用的方法有兩種。

  • 保守樂觀,即僅重傳丟失段:在大量丟包時效率低下
  • 積極悲觀,即重傳所有段:可能浪費帶寬

現在的問題是我們有沒有一種更好的方法,使得兩者兼顧哩?我們不僅想到了系統爲減少IP層分包壓力設計的MSS與計算RTT使用的字段Tcpstamps字段,它們都處於TCP報文頭部的選項字段處,所以答案出來了,對於這種情況提出了選擇性確認算法SACK(TCP Selective Acknowledgment
)。且當需要快重傳時Ack報文的TCP報文頭部的選項字段處有SACK字段,其指明瞭目前已接收到的後面報文序列號,這樣重傳時發送方就知道是應該採取樂觀還是悲觀的方式了。
下面是一個丟包報文,來瞅一瞅SACK,其隱含指出了已收到報文的相對序列號:
SAck

6.基於測量帶寬的擁塞控制算法—BBR

常說的擁塞控制應該不僅解決丟包問題還應該解決網絡資源緊缺的問題。前面講的各個擁塞控制算法,無論是快重傳還是慢重傳都是針對丟包來設計的一系列應對措施,然而還是沒有和帶寬聯繫起來過,這次就來見識一下谷歌的BBR算法,其應用於QUIC協議。

  • 基於丟包的擁塞控制缺點
    高時延,大量丟包; 隨着內存便宜,時延更高(主要是因爲緩衝區變的更大了)
  • 最佳控制點
    最大帶寬下;最小時延;最低丟包率

所以,如何準確測量帶寬,提高效率?使用BBR擁塞控制算法(已加入Linux 4.9)

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