萬字長文|全網最強TCP/IP擁塞控制總結

一.先嘮嘮嗑

在正式開始文章技術點以前,想先聊一下 我對面試中的TCP/IP問題的一些拙見 ,但願對盆友們有所幫助。
在招聘崗位描述中,幾乎必然有一條熟悉、掌握、精通TCP/IP協議、Http協議、網絡編程技術。
對於咱們求職者來講, 確定知道的越多越好,可是就像過日子同樣錢要花在刀刃上,準備面試也是同樣的,咱們該怎麼準備這部分呢?
我我的認爲合理的優先級排序是: 網絡編程技術 > Http協議 > TCP/IP協議熱點問題 > TCP/IP協議普通問題
從面試官的角度來講,面試中仍是要注重實戰,問一些邊邊角角的細節或者本身平時遇到的奇怪問題,並不能探測出 侯選人的邊界,反而讓侯選人以爲這個面試官抓不住重點。
有時候遇到一些侯選人說本身哪塊掌握的比較好,那能夠交流一下,好比以前遇到侯選人說本身讀過Redis源碼,頓時讓我頗有興趣,簡單瞭解了對方閱讀的版本以後,就開始切磋,很快就能夠探測出侯選人的所說的Redis源碼邊界。
回到網絡這塊,C/C++的話輪子比較少,有時候須要本身搞一個Socket寫個小型的服務端或者客戶端,像Python/Go這些語言作的已經很是好了,可能不到5行一個簡單的echo服務就跑起來了。由於以前本身是寫C++服務端的,回憶起第一次用Python的Tornado框架寫服務,着實被驚豔了,開發速度着實很快,性能也很不錯。
說這個的目的在於,若是 對於時間緊任務重的求職者就不要鬍子眉毛一把抓,抓幾個重點問題好好理解一下就能夠了,若是真遇到問邊角問題的面試,那也沒必要懊惱,可能大機率之後共事腦回路也不同,仍是相忘於江湖比較好。
在掌握一些重點問題的面試套路和回答以後,仍是 建議去深刻了解一些這些技術細節,更多的是去培養和鍛鍊咱們思考問題的方法和意識,以前在知乎就有這樣的問題,就像研究往年的高考題同樣, 咱們去思考TCP/IP在發展過程當中的問題以及解決方案,而且當前存在的瓶頸做出本身的判斷和思考,都是頗有益的
我想這也是打開TCP/IP的正確方式吧: 實戰派和訓練思惟派
今天和你們一塊兒學習下TCP/IP中的熱點問題: 擁塞控制本文本着實戰和 思惟訓練兼顧的原則將從如下幾個方面展開:
  • 擁塞控制的算法策略分類node

  • 擁塞控制出現的意義和目的web

  • 實現擁塞控制的幾種算法和側重點面試

  • 擁塞控制的主要過程和關鍵點算法

  • BBR算法的一些原理和思路編程

2. 我和TCP/IP協議

我在5年前研究生剛畢業的時候,在一家作深度包檢測DPI的公司待了差很少兩年,可能讀者要問啥是 深度包檢測
簡單提一下哈,深度包檢測 DPI ( Deep Packet Inspection)就是 識別TCP/IP網絡協議中各類各樣的報文,來進行流量管控和分析,在網絡安全領域應用不少,屬於通訊&互聯網領域的交叉業務
整個DPI系統是很是複雜的,目前業界有 硬件DPI和軟件DPI兩種主流類型,硬件的吞吐量大造價也高,軟件的比較靈活成本也相對低廉。
當時天天的工做就是抓包分析、用C++寫業務插件來處理各類 丟包/亂序/重傳問題等等,有時候業務須要還要單獨開發wireshark的插件來解析自定義的報文。
如今看看這份工做開啓了我和TCP/IP協議網絡的友誼之門。
在剛畢業前3年換工做的時候,幾乎總會被問到TCP/IP協議的一些東西,碰到一些專業人士問的就比較深刻,好在近兩年的經驗讓這些問題基本都在射程以內。
因此 經歷都是財富,好好學一下,說不許哪天就派上用場了呢。

三. 走心推薦

TCP/IP協議是一個協議族,若是真的很是感興趣或者工做須要 建議直接捲一捲二卷三,可是對於大多數讀者來講,應付面試或者平時排查問題掌握一些重點內容也就夠了。
TCP/IP詳解的三本書譯文不免失真,有決心和興趣的同窗能夠搞幾本英文原版的,這是豆瓣讀書上的一些評分:

四.聊聊擁塞控制算法

咱們知道TCP/IP協議棧是一個簡化的分層模型,是互聯網世界鏈接一切的基石,一塊兒來看一張 七層模型vs四層模型的簡圖:

看到一篇文章說到TCP擁塞控制算法並非簡單的計算機網絡的概念,也屬於控制論範疇,感受這個觀點很道理。緩存

TCP擁塞控制算法的目的能夠簡單歸納爲:公平競爭、充分利用網絡帶寬、下降網絡延時、優化用戶體驗,然而就目前而言要實現這些目標就不免有權衡和取捨。安全

可是如今的網絡通訊基礎設施水平一直在飛速提升,相信在將來的某個時間點這些目標均可以達到,小孩子才選擇,咱們大人全都要!服務器

算法演進

在理解擁塞控制算法以前咱們須要明確一個核心的思想:聞道有前後 術業有專攻,筆者以爲這是一個很是重要的共識問題,把A踩在泥土裏,把B吹捧到天上去,都不是很好的作法。
微信

實際的網絡環境十分複雜而且變化很快,並無哪一個擁塞控制算法能夠所有搞定,每一種算法都有本身的特定和適用領域,每種算法都是對幾個關鍵點的權衡,在沒法兼得的條件下有的算法選擇帶寬利用率,有的算法選擇通訊延時等等。網絡

在明確這個共識問題以後,咱們對待各個擁塞控制算法的態度要平和一些,不要偏激地認爲誰就是最好,幾十年前的網絡情況和如今是大相徑庭的,咱們永遠都是站在巨人的肩膀之上的,這也是科學和文明進步的推進力。

算法分類

傳統擁塞控制算法並非一蹴而就的,複雜的網絡環境和用戶的高要求推進着擁塞控制算法的優化和迭代,咱們看下基於丟包策略的傳統擁塞控制算法的幾個迭代版本,如圖所示:

與此同時還有一類算法是基於RTT延時策略來進行控制的,可是這類算法在發包速率上可能不夠激進,競爭性能不如其餘算法,所以在共享網絡帶寬時有失公平性,可是算法速率曲線倒是很平滑。

4.1 流量控制和擁塞控制

大約在1988年以前TCP/IP是沒有擁塞控制的,可是隨着網絡接入規模的發展以前僅有的端到端窗口控制已經沒法知足要求,在1986年引起大規模網絡癱瘓,此時就要提到一個重量級人物:Van Jacobson範·雅各布森

這位力挽狂瀾的人物入選了計算機名人堂Internet Hall of Fame,Van Jacobson大神提出並設計實施了TCP/IP擁塞控制,解決了當時最大的問題,來簡單看下Van Jacobson的維基百科簡介(筆者作了部分刪減):

範·雅各布森Van Jacobson是目前做爲互聯網技術基礎的TCP/IP協議棧的主要起草者,他以其在網絡性能的提高和優化的開創性成就而聞名。

2006年8月,他加入了帕洛阿爾託研究中心擔任研究員,並在位於相鄰的施樂建築羣的Packet Design公司擔任首席科學家。在此以前,他曾是思科系統公司首席科學家,並在位於勞倫斯伯克利國家實驗室的網絡研究小組任領導者。

範·雅各布森由於在提升IP網絡性能提高和優化所做的工做而爲人們所知,1988到1989年間,他從新設計了TCP/IP的流控制算法(Jacobson算法),他因設計了RFC 1144中的TCP/IP頭壓縮協議即範·雅各布森TCP/IP頭壓縮協議而廣爲人知。此外他也曾與他人合做設計了一些被普遍使用的網絡診斷工具,如traceroute,pathchar以及tcpdump 。

範·雅各布森於2012年4月入選第一批計算機名人堂,計算機名人堂簡介:https://www.internethalloffame.org/inductees/van-jacobson

如圖爲Van Jacobson計算機名人堂的簡介:

筆者找了Van Jacobson和Michael J. Karels在1988年11月發佈的關於擁塞避免和控制的論文,總計25頁,感興趣的讀者能夠查閱:

https://ee.lbl.gov/papers/congavoid.pdf

咱們經常使用的traceroute和tcpdump也是van-jacobson大神的傑做,做爲互聯網時代的受益者不禁得對這些互聯網發展早期作出巨大貢獻的開拓者、創新者、變革者心生讚歎和敬意。

海爾兄弟同樣的算法: 流量控制和擁塞控制,這也是咱們今天的主角。

流量控制和擁塞控制從漢語字面上並不能很好的區分,本質上這一對算法既有區別也有聯繫。

維基百科對於流量控制Flow Control的說明:

In data communications, flow control is the process of managing the rate of data transmission between two nodes to prevent a fast sender from overwhelming a slow receiver.

It provides a mechanism for the receiver to control the transmission speed, so that the receiving node is not overwhelmed with data from transmitting node.

在數據通訊中,流量控制是管理兩個節點之間數據傳輸速率的過程,以防止快速發送方壓倒慢速接收方。它爲接收機提供了一種控制傳輸速度的機制,這樣接收節點就不會被來自發送節點的數據淹沒。

能夠看到流量控制是通訊雙方之間約定數據量的一種機制,具體來講是藉助於TCP協議的確認ACK機制和窗口協議來完成的。

窗口分爲固定窗口和可變窗口,可變窗口也就是滑動窗口, 簡單來講就是通訊雙方根據接收方的接收狀況動態告訴發送端能夠發送的數據量,從而實現發送方和接收方的數據收發能力匹配
這個過程很是容易捕捉,使用wireshark在電腦上抓或者tcpdump在服務器上抓均可以看到,大白在本身電腦上用wireshark抓了一條:

咱們以兩個主機交互來簡單理解流量控制過程:

接收方回覆報文頭部解釋:

圖中RcvBuffer是接收區總大小,buffered data是當前已經佔用的數據,而free buffer space是當前剩餘的空間,rwnd的就是free buffer space區域的字節數。

HostB把當前的rwnd值放入報文頭部的接收窗口receive window字段中,以此通知HostA本身還有多少可用空間, 而HostA則將未確認的數據量控制在rwnd值的範圍內,從而避免HostB的接收緩存溢出。

可見 流量控制是端到端微觀層面的數據策略,雙方在數據通訊的過程當中並不關心鏈路帶寬狀況,只關心通訊雙方的接收發送緩衝區的空間大小,能夠說是個速率流量匹配策略。
流量控制就像現實生活中物流領域中A和B兩個倉庫,A往B運送貨物時只關心倉庫B的剩餘空間來調整本身的發貨量,而不關心高速是否擁堵

4.2 爲何須要擁塞控制

前面咱們提到了微觀層面點到點的流量控制,可是咱們不禁地思考一個問題: 只有流量控制夠嗎?答案是否認的
咱們還須要一個宏觀層面的控去避免網絡鏈路的擁堵,不然再好的端到端流量控制算法也面臨丟包、亂序、重傳問題,只能形成惡性循環。

咱們從一個更高的角度去看大量TCP鏈接複用網絡鏈路的通訊過程:

因此擁塞控制和每一條端到端的鏈接關係很是大,這就是流量控制和擁塞控制的深層次聯繫,所謂每一條鏈接都順暢那麼整個複雜的網絡鏈路也很大程度是通暢的。


在展開擁塞控制以前咱們先考慮幾個問題:
  • 如何感知擁塞
TCP鏈接的發送方在向對端發送數據的過程當中,須要根據當前的網絡情況來調整發送速率,因此感知能力很關鍵。
在TCP鏈接的發送方通常是基於丟包來判斷當前網絡是否發生擁塞,丟包能夠由重傳超時RTO和重複確認來作判斷。

  • 如何利用帶寬
誠然擁塞影響很大,可是一直低速發包對帶寬利用率很低也是很不明智的作法,所以要充分利用帶寬就不能太低太高發送數據,而是保持在一個動態穩定的速率來提升帶寬利用率,這個仍是比較難的,就像茫茫黑夜去躲避障礙物。
  • 擁塞時如何調整
擁塞發生時咱們須要有一套應對措施來防止擁塞惡化而且恢復鏈接流量,這也是擁塞控制算法的精要所在。

4.3 擁塞控制的細節

前面咱們提了擁塞控制的必要性以及重要問題,接下來一塊兒看下前輩們是如何設計實現精彩的擁塞控制策略的吧!

4.3.1 擁塞窗口cwnd

從流量控制能夠知道接收方在header中給出了rwnd接收窗口大小,發送方不能自顧自地按照接收方的rwnd限制來發送數據,由於網絡鏈路是複用的,須要考慮當前鏈路狀況來肯定數據量,這也是咱們要提的另一個變量cwnd,筆者找了一個關於rwnd和cwnd的英文解釋:

Congestion Window (cwnd) is a TCP state variable that limits the amount of data the TCP can send into the network before receiving an ACK.

The Receiver Window (rwnd) is a variable that advertises the amount of data that the destination side can receive.

Together, the two variables are used to regulate data flow in TCP connections, minimize congestion, and improve network performance.

筆者在rfc5681文檔中也看到cwnd的定義:
這個解釋指出了cwnd是在發送方維護的, cwnd和rwnd並不衝突,發送方須要結合rwnd和cwnd兩個變量來發送數據,如圖所示:

cwnd的大小和MSS最大數據段有直接關係,MSS是TCP報文段中的數據字段的最大長度,即MSS=TCP報文段長度-TCP首部長度。

4.3.2 擁塞控制基本策略

擁塞控制是一個動態的過程,它既要提升帶寬利用率發送儘可能多的數據又要避免網絡擁堵丟包RTT增大等問題,基於這種高要求並非單一策略能夠搞定的,所以TCP的 擁塞控制策略其實是分階段分策略的綜合過程
如圖爲典型的包含4個策略的擁塞控制:


如圖爲發生超時重傳RTO時的過程:

4.4 擁塞控制過程詳解

咱們以典型 慢啓動、擁塞避免、快速重傳、快速恢復四個過程進行闡述。
  • 慢啓動
慢啓動就是對於剛啓動的網絡鏈接,發送速度不是一步到位而是試探性增加,具體來講:鏈接最初創建時發送方初始化擁塞窗口cwnd爲m,以後發送方在一個RTT內每收到一個ACK數據包時cwnd線性自增1,發送方每通過一個RTT時間,cwnd=cwnd*2指數增加,通過一段時間增加直到cwnd達到慢啓動閾值ssthresh。
以後cwnd再也不呈指數增加從而進入擁塞避免階段(注cwnd增加的單位是MSS),固然若是在慢啓動階段還未到達閾值ssthresh而出現丟包時進入快速重傳等階段,須要注意的是若是網絡情況良好RTT時間很短,那麼慢啓動階段將很快到達一個比較高的發送速率,因此將慢啓動理解爲試探啓動更形象。
  • 擁塞避免
當慢啓動階段cwnd的值到達ssthresh時就再也不瘋狂增加,進入更加理性的線性階段直至發送丟包,本次的閾值ssthresh是上一次發生丟包時cwnd的1/2,所以這是一個承上啓下的過程。
本次發送丟包時仍然會調整ssthresh的值,具體擁塞避免增加過程:發送方每收到一個ACK數據包時將cwnd=cwnd+1/cwnd,每通過一個RTT將cwnd自增1。
  • 超時重傳和快速重傳
TCP做爲一個可靠的協議面臨的很大的問題就是丟包,丟包就要重傳所以發送方須要根據接收方回覆的ACK來確認是否丟包了,而且發送方在發送數據以後啓動定時器,如圖所示:
RTO是隨着複雜網絡環境而動態變化的,在擁塞控制中發生超時重傳將會極大拉低cwnd,若是網絡情況並無那麼多糟糕,偶爾出現網絡抖動形成丟包或者阻塞也很是常見,所以觸發的慢啓動將下降通訊性能,故出現了快速重傳機制。
所謂快速重傳時相比超時重傳而言的,重發等待時間會下降而且後續儘可能避免慢啓動,來保證性能損失在最小的程度,如圖所示:
快速重傳和超時重傳的區別在於cwnd在發生擁塞時的取值,超時重傳會將cwnd修改成最初的值,也就是慢啓動的值,快速重傳將cwnd減半,兩者都將ssthresh設置爲cwnd的一半。
從兩者的區別能夠看到,快速重傳更加主動,有利於保證鏈路的傳輸性能,可是有研究代表3個ACK的機制一樣存在問題,本文就不作深刻闡述了,感興趣的讀者能夠自主查閱。
快速重傳是基於對網絡情況沒有那麼糟糕的假設,所以在實際網絡確實還算好的時候,快速重傳仍是頗有用的,在不好的網絡環境不少算法都很難保證效率的。
  • 快速恢復
在快速重傳以後就會進入快速恢復階段,此時的cwnd爲上次發生擁塞時的cwnd的1/2,以後cwnd再線性增長重複以前的過程

4.5 TCP算法版本和擁塞控制

實際上TCP算法有不少版本,每一個版本存在一些差別,在這裏簡單看一下維基百科的介紹:

  • 算法命名規則

TCP+算法名的命名方式最先出如今Kevin Fall和Sally Floyd1996年發佈的論文中。

  • TCP Tahoe 和TCP Reno

這兩個算法代號取自太浩湖Lake Tahoe和裏諾市,二者算法大體一致,對於丟包事件判斷都是以重傳超時retransmission timeout和重複確認爲條件,可是對於重複確認的處理二者有所不一樣,對於超時重傳RTO狀況兩個算法都是將擁塞窗口降爲1個MSS,而後進入慢啓動階段。

TCP Tahoe算法:若是收到三次重複確認即第四次收到相同確認號的分段確認,而且分段對應包無負載分段和無改變接收窗口的話,Tahoe算法則進入快速重傳,將慢啓動閾值改成當前擁塞窗口的一半,將擁塞窗口降爲1個MSS,並從新進入慢啓動階段。

TCP Reno算法:若是收到三次重複確認,Reno算法則進入快速重傳只將擁塞窗口減半來跳過慢啓動階段,將慢啓動閾值設爲當前新的擁塞窗口值,進入一個稱爲快速恢復的新設計階段。TCP New Reno

TCP New Reno是對TCP Reno中快速恢復階段的重傳進行改善的一種改進算法,New Reno在低錯誤率時運行效率和選擇確認SACK至關,在高錯誤率仍優於Reno。

  • TCP BIC 和TCP CUBIC

TCP BIC旨在優化高速高延遲網絡的擁塞控制,其擁塞窗口算法使用二分搜索算法嘗試找到能長時間保持擁塞窗口最大值,Linux內核在2.6.8至2.6.18使用該算法做爲默認TCP擁塞算法。

CUBIC則是比BIC更溫和和系統化的分支版本,其使用三次函數代替二分算法做爲其擁塞窗口算法,而且使用函數拐點做爲擁塞窗口的設置值,Linux內核在2.6.19後使用該算法做爲默認TCP擁塞算法。

  • TCP PRR

TCP PRR是旨在恢復期間提升發送數據的準確性,該算法確保恢復後的擁塞窗口大小盡量接近慢啓動閾值。在Google進行的測試中,能將平均延遲下降3~10%恢復超時減小5%,PRR算法後做爲Linux內核3.2版本默認擁塞算法。TCP BBR

TCP BBR是由Google設計於2016年發佈的擁塞算法,該算法認爲隨着網絡接口控制器逐漸進入千兆速度時,分組丟失不該該被認爲是識別擁塞的主要決定因素,因此基於模型的擁塞控制算法能有更高的吞吐量和更低的延遲,能夠用BBR來替代其餘流行的擁塞算法。

Google在YouTube上應用該算法,將全球平均的YouTube網絡吞吐量提升了4%,BBR以後移植入Linux內核4.9版本。

其中比較有名的Vegas算法是大約在1995年由亞利桑那大學的研究人員拉里·彼得森和勞倫斯·布拉科夫提出,這個新的TCP擁塞算法之內華達州最大的城市拉斯維加斯命名,後成爲TCP Vegas算法。

關於基於RTT的TCP Vegas算法的詳細介紹能夠查閱文檔:

http://www.cs.cmu.edu/~srini/15-744/F02/readings/BP95.pdf

文檔對Vegas算法和New Reno作了一些對比,咱們從直觀圖形上能夠看到Vegas算法更加平滑,相反New Reno則表現除了較大的波動呈鋸齒狀,如圖所示:

實際上還有更細粒度的分類,因爲不是今天的重點,就再也不深刻展開了,當前使用的擁塞控制算法仍是基於丟包Loss-Based做爲主流。

五.複雜的網絡環境和擁塞控制

咱們知道在網絡鏈路中鏈接的數量是動態變化且數量巨大的,每一條鏈接都面臨着一個黑盒子式的網絡環境,這並不像咱們平時出行時看看地圖就知道哪裏堵了,爲了維護一個好的網絡環境,每一條鏈接都須要遵照一些約定。

若是鏈接端都無所顧忌地發生數據包,那麼網絡鏈路很快就到了瓶頸了,數據通訊徹底沒法保障,因此要到達一個穩定高效的網絡環境仍是須要費很大心思的,這其中有兩個重要的概念:公平性和收斂性

說來慚愧筆者在網絡上找了不少資料去理解TCP擁塞控制的公平性和收斂性,可是仍然沒有得到一個很好的權威解釋,因此只能結合一些資料和自身的理解去闡述所謂的公平性和收斂性。

5.1 AIMD特性

筆者認爲公平性是相對於網絡鏈路中的全部鏈接而言的,這些共享鏈路的鏈接啓動和結束的時間不一樣,在實際的交互過程當中每條鏈接佔有帶寬的機會是均等的,而且因爲帶寬限制鏈接雙方通訊的數據量是動態調整而且近似收斂於某個值,也就是呈現一個鋸齒狀或者更加平滑的波動曲線,對於基於丟包的擁塞控制算法而言AIMD線性增乘性減策略起了關鍵控制做用。

接下來咱們來重點看下AIMD特性,先來貼一張經典的圖,直觀看AIMD的過程:

看看維基百科對於AIMD的定義:

The additive-increase/multiplicative-decrease(AIMD) algorithm is a feedback control algorithm best known for its use in TCP congestion control.

AIMD combines linear growth of the congestion window with an exponential reduction when congestion is detected.

Multiple flows using AIMD congestion control will eventually converge to use equal amounts of a shared link.

The related schemes of multiplicative-increase/multiplicative-decrease (MIMD) and additive-increase/additive-decrease (AIAD) do not reach stability.

簡單翻譯一下:線性增長乘性減小算法是一個反饋控制算法,因其在TCP擁塞控制中的使用而廣爲人知,AIMD將線性增長擁塞窗口和擁塞時乘性減小窗口相結合,基於AIMD的多個鏈接理想狀態下會達到最終收斂,共享相同數量的網絡帶寬,與其相關的乘性增乘性減MIMD策略和增性加增性減小AIAD都沒法保證穩定性。

AIMD相比MIMD和AIAD在鏈接進入擁塞避免階段使用試探線性加策略而不是乘性加策略更加安全,在探測丟包時則大幅度乘性減小到1/2這樣對於緩解擁塞會有比較好的效果更加快速,相反若是探測到丟包時採用線性減小AD可能擁塞持續的時間會更長,整體來講AIMD算是一個比較簡單實用的工程版本的反饋控制,也具有可工程收斂性,於是被普遍實用。

5.2 弱網絡環境下的AIMD

時間拉回20多年前,在互聯網早期幾乎全部的設備都是經過有線網絡進行鏈接通訊的,這也是擁塞控制在設計以後一直都起到不錯做用的重要因素,有線鏈接的網絡穩定性比較好,所以把丟包做爲網絡擁堵的一個特徵也很正常。

再拉回到如今,從2010年以後移動互聯網蓬勃發展,移動終端的持有量已經能夠稱爲海量,無線網絡的引入讓網絡環境變得更加複雜,所以不穩定丟包變得更加頻繁,可是這時的丟包就不必定是網絡擁堵形成的了,由於整個數據包通過多重路由、交換機、基站等基礎通訊設備每一個環節均可能發生異常。

在弱網環境下,尤爲是移動互聯網中以前的基於AIMD的擁塞控制策略可能會因爲丟包的出現而大幅下降網絡吞吐量,從而對網絡帶寬的利用率也大大降低,這時咱們採用更加激進的控制策略,或許能夠得到更好的效果和用戶體驗。

惡意丟包的狀況下,基於AIMD的擁塞控制確實就至關於被限速了,由於AIMD確實有些保守謹慎了,這個其實也很好理解的哈。

咱們都知道在移動網絡環境下是由終端以無線形式和附近的基站交互數據,以後數據傳輸至核心網,最後落到具體的服務器所在的有線網絡,其中最後一千米的區域屬於高延時場景,有線網絡屬於低延時高帶寬場景。

在國外有相關實驗證實弱網環境下RTT的變化對於使用傳統擁塞控制算法下網絡吞吐量的影響,數據和曲線如圖所示:

實驗含義:RTT的增大影響了好比CUBIC這類擁塞控制算法的慢啓動等階段,咱們知道慢啓動階段每通過1個RTT週期擁塞窗口cwnd將加倍,可是更大的RTT就意味着發送方以很低的速率發送數據,更多的時間是空閒的,發包的加速度極大將低了,因此整個吞吐量就降低很明顯。

看下實驗者的原文表述:

The delay before acknowledgment packets are received (= latency) will have an impact on how fast the TCP congestion window increases (hence the throughput).

When latency is high, it means that the sender spends more time idle (not sending any new packets), which reduces how fast throughput grows.

六.強悍的BBR算法

BBR算法是個主動的閉環反饋系統,通俗來講就是根據帶寬和RTT延時來不斷動態探索尋找合適的發送速率和發送量。

看下維基百科對BBR算法的說明和資料:

相關文獻:https://queue.acm.org/detail.cfm?id=3022184

TCP BBR(Bottleneck Bandwidth and Round-trip propagation time)是由Google設計,並於2016年發佈的擁塞算法,以往大部分擁塞算法是基於丟包來做爲下降傳輸速率的信號,而BBR基於模型主動探測。

該算法使用網絡最近出站數據分組當時的最大帶寬和往返時間來建立網絡的顯式模型。數據包傳輸的每一個累積或選擇性確認用於生成記錄在數據包傳輸過程和確認返回期間的時間內所傳送數據量的採樣率。

該算法認爲隨着網絡接口控制器逐漸進入千兆速度時,分組丟失不該該被認爲是識別擁塞的主要決定因素,因此基於模型的擁塞控制算法能有更高的吞吐量和更低的延遲,能夠用BBR來替代其餘流行的擁塞算法例如CUBIC。

Google在YouTube上應用該算法,將全球平均的YouTube網絡吞吐量提升了4%,在一些國家超過了14%。BBR以後移植入Linux內核4.9版本,而且對於QUIC可用。

6.1 丟包反饋策略存在的問題

基於丟包反饋屬於被動式機制,根源在於這些擁塞控制算法依據是否出現丟包事件來判斷網絡擁塞作減窗調整,這樣就可能會出現一些問題:

  • 丟包即擁塞
    現實中網絡環境很複雜會存在錯誤丟包,不少算法沒法很好區分擁塞丟包和錯誤丟包,所以在存在必定錯誤丟包的前提下在某些網絡場景中並不能充分利用帶寬。

  • 緩衝區膨脹問題BufferBloat
    網絡鏈接中路由器、交換機、核心網設備等等爲了平滑網絡波動而存在緩衝區,這些緩存區就像輸液管的膨脹部分讓數據更加平穩,可是Loss-Based策略在最初就像網絡中發生數據相似於灌水,此時是將Buffer所有算在內的,一旦buffer滿了,就可能出現RTT增長丟包等問題,就至關於有的容量本不應算在其中,可是策略是基於包含Buffer進行預測的,特別地在深緩衝區網絡就會出現一些問題。

  • 網絡負載高但無丟包事件
    假設網絡中的負載已經很高了,只要沒有丟包事件出現,算法就不會主動減窗下降發送速率,這種狀況下雖然充分利用了網絡帶寬,同時因爲一直沒有丟包事件出現發送方仍然在加窗,表現出了較強的網絡帶寬侵略性,加劇了網絡負載壓力。

  • 高負載丟包
    高負載無丟包狀況下算法一直加窗,這樣能夠預測丟包事件可能很快就出現了,一旦丟包出現窗口將呈現乘性減小,由高位發送速率迅速下降會形成整個網絡的瞬時抖動性,整體呈現較大的鋸齒狀波動。

  • 低負載高延時丟包
    在某些弱網環境下RTT會增長甚至出現非擁塞引發丟包,此時基於丟包反饋的擁塞算法的窗口會比較小,對帶寬的利用率很低,吞吐量降低很明顯,可是實際上網絡負載並不高,因此在弱網環境下效果並非很是理想。

6.2 TCP BBR算法基本原理

前面咱們提到了一些Loss-Based算法存在的問題,TCP BBR算法是一種主動式機制,簡單來講BBR算法再也不基於丟包判斷而且也再也不使用AIMD線性增乘性減策略來維護擁塞窗口,而是分別採樣估計極大帶寬和極小延時,並用兩者乘積做爲發送窗口,而且BBR引入了Pacing Rate限制數據發送速率,配合cwnd使用來下降衝擊。

提及BBR算法總讓我想起一款小遊戲flappy bird:

咱們須要不斷調整bird的飛行高度,可是太高太低震盪太多就很容易掛掉,因此若是可以平滑一些或許會飛得更遠哦!

在開始BBR算法以前,咱們先來了解幾個有用的術語:

  • BDP帶寬延時積

BDP是Bandwidth-Delay Product的縮寫,能夠翻譯爲帶寬延時積,咱們知道帶寬的單位是bps(bit per second),延時的單位是s,這樣BDP的量綱單位就是bit,從而咱們知道BDP就是衡量一段時間內鏈路的數據量的指標。這個能夠形象理解爲水管灌水問題,帶寬就是水管的水流速度立方米/s,延時就是灌水時間單位s,兩者乘積咱們就能夠知道當前水管內存儲的水量了,這是BBR算法的一個關鍵指標,來看一張陶輝大神文章中的圖以及一些網絡場景中的BDP計算:

  • 長肥網絡

咱們把具備長RTT往返時間和高帶寬的網絡成爲長肥網絡或者長肥管道,它的帶寬延時積BDP很大大,這種網絡理論上吞吐量很大也是研究的重點。

  • TCP Pacing機制

能夠簡單地理解TCP Pacing機制就是將擁塞控制中數據包的作平滑發送處理,避免數據的突發下降網絡抖動。

6.2.1 TCP帶寬和延時的測量

BBR算法的一些思想在以前的基於延時的擁塞控制算法中也有出現,其中必有有名的是TCP WestWood算法。

TCP Westwood改良自New Reno,不一樣於以往其餘擁塞控制算法使用丟失來測量,其經過對確認包測量來肯定一個合適的發送速度,並以此調整擁塞窗口和慢啓動閾值。其改良了慢啓動階段算法爲敏捷探測和設計了一種持續探測擁塞窗口的方法來控制進入敏捷探測,使連接儘量地使用更多的帶寬。

TCP WestWood算法也是基於帶寬和延時乘積進行設計的,可是帶寬和延時兩個指標沒法同時測量,由於這兩個值是有些矛盾的極值,要測量最大帶寬就要發送最大的數據量可是此時的RTT可能會很大,若是要測量最小的RTT那麼久意味着數據量很是少最大帶寬就沒法得到。

TCP BBR算法採用交替採樣測量兩個指標,取一段時間內的帶寬極大值和延時極小值做爲估計值,具體的實現本文就不展開了。

6.2.2 發送速率和RTT曲線

前面提到了BBR算法核心是尋找BDP最優工做點,在相關論文中給出了一張組合的曲線圖,咱們一塊兒來看下:


1. 曲線圖示說明:
這張圖是由兩個圖組合而成,目前是展現[數據發送速率vs網絡數據]和[RTTvs網絡數據]的關係,橫軸是網絡數據數量。

兩個縱軸從上到下分別爲RTT和發送速率,而且整個過程分爲了3個階段:應用限制階段、帶寬限制階段、緩衝區限制階段

2. 曲線過程說明:

  • app limit應用限制階段
    在這個階段是應用程序開始發送數據,目前網絡通暢RTT基本保持固定且很小,發送速率與RTT成反比,所以發送速率也是線性增長的,能夠簡單認爲這個階段有效帶寬並無達到上限,RTT是幾乎固定的沒有明顯增加。
  • band limit帶寬限制階段
    隨着發送速率提升,網絡中的數據包愈來愈多開始佔用鏈路Buffer,此時RTT開始增長髮送速率再也不上升,有效帶寬開始出現瓶頸,可是此時鏈路中的緩存區並無佔滿,所以數據還在增長,RTT也開始增長。
  • buffer limit緩衝區限制階段
    隨着鏈路中的Buffer被佔滿,開始出現丟包,這也是探測到的最大帶寬,這個節點BDP+BufferSize也是基於丟包的控制策略的做用點。

3. 一些見解

網上有一些資料都說起到了這張圖,其中的一些解釋也並不算很是清晰,結合這些資料和本身的認識,筆者認爲在網絡鏈路的緩存區沒有被使用時RTT爲最小延時MinRTT,在網絡鏈路緩衝區被佔滿時出現最大帶寬MaxBW(鏈路帶寬+鏈路緩存),可是此時的MaxBW和MinRTT並非最優的而是水位比較高的水平,有數據代表按照2ln2的增益計算此時爲3BDP,整個過程當中MinRTT和MaxBW是分開探測的,由於這兩者是不能同時被測量的。

6.2.3 BBR算法的主要過程

BBR算法和CUBIC算法相似,也一樣有幾個過程:StartUp、Drain、Probe_BW、Probe_RTT,來看下這幾個狀態的遷移狀況:

  • StartUp慢啓動階段
    BBR的慢啓動階段相似於CUBIC的慢啓動,一樣是進行探測式加速區別在於BBR的慢啓動使用2ln2的增益加速,過程當中即便發生丟包也不會引發速率的下降,而是依據返回的確認數據包來判斷帶寬增加,直到帶寬再也不增加時就中止慢啓動而進入下一個階段,須要注意的是在尋找最大帶寬的過程當中產生了多餘的2BDP的數據量,關於這塊能夠看下英文原文的解釋:

To handle Internet link bandwidths spanning 12 orders of magnitude, Startup implements a binary search for BtlBw by using a gain of 2/ln2 to double the sending rate while delivery rate is increasing. This discovers BtlBw in log2BDP RTTs but creates up to 2BDP excess queue in the process.

  • Drain排空階段
    排空階段是爲了把慢啓動結束時多餘的2BDP的數據量清空,此階段發送速率開始降低,也就是單位時間發送的數據包數量在降低,直到未確認的數據包數量<BDP時認爲已經排空,也能夠認爲是RTT再也不降低爲止,排空階段結束。

  • ProbeBW帶寬探測階段
    通過慢啓動和排空以後,目前發送方進入穩定狀態進行數據的發送,因爲網絡帶寬的變化要比RTT更爲頻繁,所以ProbeBW階段也是BBR的主要階段,在探測期中增長髮包速率若是數據包ACK並無受影響那麼就繼續增長,探測到帶寬下降時也進行發包速率降低。

  • ProbeRTT延時探測階段
    前面三個過程在運行時均可能進入ProbeRTT階段,當某個設定時間內都沒有更新最小延時狀態下開始下降數據包發送量,試圖探測到更小的MinRTT,探測完成以後再根據最新數據來肯定進入慢啓動仍是ProbeBW階段。

們來看一下這四個過程的示意圖:

曲線說明:這兩個座標給出了10Mbps和40msRTT的網絡環境下CUBIC和BBR的一個對比過程,在上面的圖中藍色表示接收者,紅色表示CUBIC,綠色表示BBR,在下面的圖中給出了對應上圖過程當中的RTT波動狀況,紅色表明CUBIC,綠色表明BBR。

6.2.4 BBR算法的一些效果

有一些文章認爲BBR有鮮明的特色,把擁塞控制算法分爲BBR以前和BBR以後,可見BBR仍是有必定影響,可是BBR算法也不是銀彈,不過能夠先看看BBR算法在谷歌推進下的一些應用效果,其中包括吞吐量、RTT、丟包率影響:


從圖中咱們能夠看到在YouTube應用BBR算法以後,就吞吐量廣泛有4%左右的提高,特別地在日本的提高達到14%,RTT的降低更爲明顯平均下降33%,其中IN(猜想是印度地區)達到50%以上,在丟包率測試中BBR並不想CUBIC那麼敏感,在丟包率達到5%是吞吐量纔開始明顯降低。

寫在最後

TCP/IP協議內容很是多,同時也帶有年代感,因此我的建議不要總拘泥於網上的那些俗套問題,能夠多看看當前的新趨勢,好比HTTP3.0、SDN、DPDK這些新鮮的東西,並且不少書籍也比較早,有條件的同窗能夠看一些最新的外文資料來了解前沿信息,尤爲是對於作音視頻或者通訊領域的同窗仍是頗有好處的。


送福利,公衆號後臺回覆「模擬題」獲取算法筆試模擬題精解合集,該書籍爲阿里雲開發電子書系列之一(阿里雲開發者社區有很多高質量技術文章,你們能夠去觀摩學習,有不少書籍都是能夠直接免費下載的),涵蓋 70+算法題目,近 30 種大廠筆試常考知識點。但願在你「面試戰場」上可以助你一臂之力。

推 薦 閱 讀

快快加入咱們——「阿里雲-ECS/神龍計算平臺」 招人啦
面試官:會玩牌吧?給我講講洗牌算法和它的應用場景吧!

面了 7 輪 Google,最終仍是逃不脫被掛的命運

從一道面試題談談一線大廠碼農應該具有的基本能力

終於跟女友解釋清楚了什麼是雲計算


- 歡迎加入互聯網大廠內推羣 & 技術交流羣 -



給個在看,鼓勵一下!

本文分享自微信公衆號 - 程序猿石頭(tangleithu)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索