精品一区二区三区在线成人,欧美精产国品一二三区,Ji大巴进入女人66h,亚洲春色在线视频

斯坦福 CS144 計算機網(wǎng)絡(luò)播客:TCP 擁塞控制

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
本文將以 Stanford CS 144 課程的核心知識為基礎(chǔ),帶你深入理解 TCP 擁塞控制的來龍去脈,從它是什么、為什么重要,到核心算法 AIMD,再到 TCP 各個版本的演進。

在計算機網(wǎng)絡(luò)的世界里,數(shù)據(jù)包就像高速公路上飛馳的汽車。當車流量恰到好處時,一切井然有序;但如果車輛瞬間涌入,遠超道路承載能力,就會發(fā)生嚴重的堵車。網(wǎng)絡(luò)中的“堵車”就是我們今天要討論的核心話題—— 擁塞(Congestion) 。

本文將以 Stanford CS 144 課程的核心知識為基礎(chǔ),帶你深入理解 TCP 擁塞控制的來龍去脈,從它是什么、為什么重要,到核心算法 AIMD,再到 TCP 各個版本的演進。

什么是擁塞控制?

首先,我們需要區(qū)分一個非常相似但本質(zhì)不同的概念: 流量控制 (Flow Control) 。流量控制是點對點的問題,它確保發(fā)送方不會因為發(fā)送速度過快而淹沒接收方。這好比兩個人對話,一方說得太快,另一方需要讓他“慢一點”。

而 擁塞控制 (Congestion Control) 則是一個全局性的問題。它關(guān)注的是整個網(wǎng)絡(luò)的承載能力,確保數(shù)據(jù)發(fā)送方不會向網(wǎng)絡(luò)中注入過多的數(shù)據(jù),導(dǎo)致路由器等網(wǎng)絡(luò)設(shè)備不堪重負。它管理者是“所有發(fā)送者”與“網(wǎng)絡(luò)”之間的關(guān)系。

簡單來說,擁塞控制是一種資源管理機制,它的目標是:

  • 防止網(wǎng)絡(luò)過載 :避免路由器緩沖區(qū)溢出和大規(guī)模的數(shù)據(jù)包丟失。
  • 保證資源公平分配 :讓多個數(shù)據(jù)流(flow)可以相對公平地共享有限的網(wǎng)絡(luò)帶寬。

有趣的是,IP 協(xié)議本身并不提供擁塞反饋,因此,擁塞控制的重任落在了傳輸層,主要由 終端主機 (end-hosts) 上的 TCP 協(xié)議來完成。這正是著名的“端到端原則”的一個經(jīng)典體現(xiàn)。但這又引申出另一個問題:端是不知道網(wǎng)絡(luò)中各節(jié)點的狀態(tài)的,因此想在端到端控制網(wǎng)絡(luò)擁塞是一個充滿挑戰(zhàn)的任務(wù)。

擁塞的危害:從性能下降到網(wǎng)絡(luò)崩潰

當發(fā)送方注入網(wǎng)絡(luò)的數(shù)據(jù)量超過了某個瓶頸路由器的處理能力時,數(shù)據(jù)包就會開始在路由器的緩沖區(qū)中排隊。適度的排隊是正常的,它表明網(wǎng)絡(luò)鏈路得到了充分利用。

然而,當數(shù)據(jù)注入速度持續(xù)高于處理速度時,路由器的緩沖區(qū)最終會被填滿,后續(xù)到達的數(shù)據(jù)包將被無情地丟棄。這就是 丟包 (Packet Loss) 。

丟包會觸發(fā)發(fā)送方的重傳機制,但這會導(dǎo)致一個惡性循環(huán):

  1. 網(wǎng)絡(luò)已經(jīng)擁塞,發(fā)生丟包。
  2. 發(fā)送方檢測到丟包,認為數(shù)據(jù)未送達,于是重傳數(shù)據(jù)。
  3. 重傳的數(shù)據(jù)包進一步加劇了網(wǎng)絡(luò)的擁塞。

在極端情況下,這可能導(dǎo)致 擁塞崩潰 (Congestion Collapse) ——網(wǎng)絡(luò)中充斥著大量重傳的數(shù)據(jù)包,但幾乎沒有任何有效的數(shù)據(jù)能夠成功傳輸?shù)侥康牡兀W(wǎng)絡(luò)吞吐量急劇下降,甚至趨近于零。

理想模型:帶寬時延積 (BDP)

那么,一個理想的發(fā)送方應(yīng)該以多快的速度發(fā)送數(shù)據(jù)呢?TCP 引入了一個名為 擁塞窗口 (Congestion Window) ,通常寫作 cwnd 的變量來控制。它表示在收到確認(ACK)之前,可以發(fā)送到網(wǎng)絡(luò)中的最大數(shù)據(jù)量。


注意:實際的發(fā)送窗口大小是 cwnd 和接收方通告的接收窗口 rwnd 中的較小值,即 EffectiveWindow = min(cwnd, rwnd)

在理想狀態(tài)下,我們希望 cwnd 的大小恰好能“填滿”從發(fā)送方到接收方的網(wǎng)絡(luò)路徑。這個理想值就是 帶寬時延積 (Bandwidth-Delay Product, BDP) 。

BDP 的計算公式為:

它代表了在網(wǎng)絡(luò)路徑中可以容納的最大數(shù)據(jù)量。我們可以用一個簡單的圖來理解:

Sender                                                     Receiver
    |                                                            |
    |------------------ The "Pipe" of the Network ---------------|
    |                                                            |
    v                                                            v

    <------------------ RTT (Round-Trip Time) ------------------->

    Data in flight to fill the pipe = Bandwidth * RTT

例如,如果一條鏈路的帶寬是 5 Mbit/s,往返時延(RTT)是 100 ms,那么:

BDP = 5,000,000 bits/s * 0.1 s = 500,000 bits = 62,500 bytes = 62.5 KB

這意味著,為了讓鏈路時刻保持繁忙而又不產(chǎn)生排隊,發(fā)送方需要維持一個 62.5 KB 大小的擁塞窗口。

然而,現(xiàn)實是殘酷的。TCP 發(fā)送方在運行時 無法預(yù)知 瓶頸鏈路的帶寬、網(wǎng)絡(luò)中是否存在其他競爭流量,以及沒有排隊時的最小 RTT。因此,TCP 需要一個動態(tài)的算法來探測并逼近這個理想的 cwnd 值。

AIMD:TCP 擁塞控制的基石

為了動態(tài)調(diào)整 cwnd,TCP 采用了一種被稱為 加性增窗、乘性減窗 (Additive Increase, Multiplicative Decrease, AIMD) 的經(jīng)典算法。

這個算法的邏輯非常優(yōu)雅,可以概括為“謹慎探測,快速避讓”。

加性增窗 (Additive Increase, AI)

當網(wǎng)絡(luò)狀態(tài)良好時(即數(shù)據(jù)包被成功確認),TCP 會認為網(wǎng)絡(luò)仍有余力,于是緩慢地增加其擁塞窗口,以探測更多的可用帶寬。

具體來說,在擁塞避免階段,每經(jīng)過一個 RTT,如果所有數(shù)據(jù)包都被成功確認,cwnd 就會增加一個 最大段大小 (Maximum Segment Size, MSS) 。

實現(xiàn)細節(jié):為了在每個 RTT 內(nèi)增加 1 個 MSS,TCP 的策略是每收到一個 ACK,cwnd 就增加 MSS / cwnd。這樣,在一個窗口的數(shù)據(jù)被全部確認后,cwnd 大小正好增加了約 1 個 MSS。詳細解釋一下:

  • 目標: 在擁塞避免階段,每經(jīng)過一個 RTT,cwnd 增加 1 個 MSS。
  • 挑戰(zhàn): 發(fā)送方并不知道 RTT 的精確時長。它只能通過“收到一個窗口數(shù)據(jù)的 ACK”來近似一個 RTT 周期。
  • 推導(dǎo):

假設(shè)當前 cwnd 是 10 個 MSS。這意味著在一個 RTT 內(nèi),發(fā)送方會發(fā)出 10 個數(shù)據(jù)段,并期望收到 10 個對應(yīng)的 ACK。

我們的目標是在收到這 10 個 ACK 后,cwnd 的總增量為 1 個 MSS。

那么,將這個總增量平均分配到每個到來的 ACK 上,就是最自然的方法。

每個 ACK 應(yīng)該帶來的增量 = 總增量 / ACK 數(shù)量 = 1 MSS / 10

這里的 10 正好是當前 cwnd 能容納的段數(shù),即 cwnd / MSS

所以,每個 ACK 帶來的增量 = 1 MSS / (cwnd / MSS) = MSS * MSS / cwnd (如果 cwnd 以字節(jié)為單位),或者更通俗地寫成 MSS / cwnd

  • 結(jié)論: 這個公式 cwnd += MSS / cwnd 是一種平滑的、在 RTT 周期內(nèi)實現(xiàn) +1 MSS 目標的工程實現(xiàn)。

乘性減窗 (Multiplicative Decrease, MD)

當網(wǎng)絡(luò)發(fā)生擁塞(即檢測到丟包)時,TCP 必須迅速降低其發(fā)送速率,以緩解網(wǎng)絡(luò)壓力。這個反應(yīng)必須是劇烈的。

TCP 的策略是將 cwnd 直接 減半 (cwnd = cwnd / 2)。這種大幅度的削減能夠快速為網(wǎng)絡(luò)“降溫”,為恢復(fù)穩(wěn)定創(chuàng)造條件。

“鋸齒”形的 cwnd 變化

AIMD 算法導(dǎo)致 cwnd 的變化呈現(xiàn)出一種非常典型的“鋸齒狀”模式。

圖片

這種不斷探測(增加)和快速后退(減半)的機制,使得 TCP 能夠動態(tài)地適應(yīng)網(wǎng)絡(luò)負載的變化,并在多個 TCP 流之間實現(xiàn)相對的公平。

然而,AIMD 也有一個固有的問題:它的吞吐量與 1/√p(p 是丟包率)成正比,與 1/RTT 成正比。這意味著,RTT 越長的連接(例如跨國連接),其吞吐量會越低,因為它增加 cwnd 的速度更慢。這在一定程度上懲罰了距離較遠的連接。

  • 為什么與 1/RTT 成正比? 這個比較好理解。吞吐量的基本定義是 窗口大小 / 時間。在這里,就是 cwnd / RTT。在一個 RTT 時間內(nèi),我們最多可以發(fā)送 cwnd 大小的數(shù)據(jù)。因此,RTT 越長,單位時間能發(fā)送的輪次就越少,吞吐量自然就越低。
  • 為什么與 1/√p 成正比? (p 是丟包率)

想象一下 AIMD 的“鋸齒”圖。cwnd 從 W/2 增長到 W 時發(fā)生一次丟包。

在一個丟包周期內(nèi),發(fā)送的數(shù)據(jù)包總數(shù)約等于這個鋸齒下方的面積。這個面積大致和 W2 成正比。

丟包率 p 的含義是“平均每發(fā)送 1/p 個包,就會發(fā)生一次丟包”。

因此,一個丟包周期內(nèi)發(fā)送的數(shù)據(jù)包總數(shù)也約等于 1/p

所以我們得出 W2 ∝ 1/p,進而 W ∝ 1/√p

因為吞吐量正比于平均窗口大小,而平均窗口大小又正比于最大窗口 W,所以 吞吐量 ∝ 1/√p 。

  • 綜合來看: 這個公式揭示了標準 TCP 的一個內(nèi)在特性:在有損網(wǎng)絡(luò)中,丟包率對吞吐量的影響是平方根級別的;而在高延遲網(wǎng)絡(luò)中,RTT 對吞吐量的影響是線性的。這也解釋了為什么長距離(高 RTT)連接在有少量丟包時性能下降如此明顯。

慢啟動:快速啟動,指數(shù)增長

如果一個新的 TCP 連接從一個很小的 cwnd (例如 1-3 個 MSS) 開始,使用 AIMD 的加性增長,那么它需要很多個 RTT 才能達到一個合理的窗口大小,這個過程太慢了。

為了解決這個問題,TCP 引入了 慢啟動 (Slow-Start) 機制。雖然名字里有“慢”,但它的增長方式實際上是 指數(shù)級 (exponential) 的,非常快。

為什么叫慢啟動呢? 這是一個歷史遺留的命名問題,關(guān)鍵在于“和誰比”。在“慢啟動”算法被發(fā)明之前,TCP 連接一旦建立,發(fā)送方會立即向網(wǎng)絡(luò)中注入接收方窗口 (rwnd) 允許的全部數(shù)據(jù)。如果網(wǎng)絡(luò)中間某個路由器處理不了這么大的瞬時流量,就會立即導(dǎo)致?lián)砣痛罅縼G包。

相比于那種“瞬間洪水”式的野蠻行為,從 cwnd=1 開始,然后以指數(shù)級增長的方式“慢慢地”將數(shù)據(jù)注入網(wǎng)絡(luò),已經(jīng)是一種非常“溫柔”和“緩慢”的啟動方式了。所以,“慢啟動”的“慢”是相對于過去那種簡單粗暴的實現(xiàn)而言的。

  • 初始階段 :連接建立后,cwnd 被初始化為一個較小的值,例如 IW (Initial Window),通常為 2-4 個 MSS,在現(xiàn)代系統(tǒng)中甚至可以達到 10 個 MSS。
  • 指數(shù)增長 :在慢啟動階段,每收到一個 ACK,cwnd 就會增加 1 個 MSS。這意味著,每經(jīng)過一個 RTT,cwnd 就會 翻倍 (具體可以參考下面的例子)。
  • 退出條件 :慢啟動階段會在以下兩種情況之一發(fā)生時結(jié)束:

當 cwnd 的值超過一個預(yù)設(shè)的 慢啟動閾值 (slow-start threshold, ssthresh) 時,TCP 會從慢啟動階段切換到擁塞避免階段(即 AIMD 的加性增長)。

當檢測到丟包時。

慢啟動的目的是在連接初期快速探測網(wǎng)絡(luò)的可用容量,盡快將 cwnd 提升到一個合理的量級,然后再轉(zhuǎn)入更為謹慎的 AIMD 階段。

MSS (Maximum Segment Size) 的確定

MSS 并不是一個固定的常量,而是在 TCP 連接建立的“三次握手”階段,由通信雙方 協(xié)商 確定的。它的核心目標是盡可能地利用網(wǎng)絡(luò)鏈路的承載能力,同時避免 IP 層的數(shù)據(jù)包分片。

MSS 的大小受到鏈路層最大傳輸單元 MTU (Maximum Transmission Unit) 的限制。其理想計算公式為:

MSS = MTU - IP Header Size - TCP Header Size

協(xié)商過程:

  • 在三次握手時,客戶端在第一個 SYN 包中,通過 TCP 選項字段宣告自己的 MSS 值。
  • 服務(wù)器在返回的 SYN-ACK 包中,也會宣告自己的 MSS 值。
  • 最終,雙方會選擇兩者中 較小 的 MSS 值作為本次連接的最終 MSS。這確保了任何一方發(fā)送的數(shù)據(jù)段都不會超過對方的處理能力。

生產(chǎn)中的典型值:

  • 在最常見的以太網(wǎng)(Ethernet)環(huán)境中,MTU 通常是 1500 字節(jié)
  • 標準的 IP 頭部大小為 20 字節(jié),TCP 頭部大小也為 20 字節(jié)(不含選項)。
  • 因此,最常見的 MSS 值為:1500 - 20 - 20 = 1460 字節(jié)
  • 如果你在使用撥號上網(wǎng)(PPPoE),它會額外占用 8 字節(jié),導(dǎo)致 MTU 為 1492 字節(jié),MSS 則為 1452 字節(jié)。VPN 或其他隧道技術(shù)也可能進一步減小 MTU,從而影響 MSS 的取值。

現(xiàn)代操作系統(tǒng)通常會自動處理這個協(xié)商過程。此外,還有一種更高級的機制叫 路徑 MTU 發(fā)現(xiàn) (Path MTU Discovery, PMTUD) ,它能動態(tài)地發(fā)現(xiàn)從源到目的地的整個路徑上最小的 MTU,從而更精確地設(shè)置 MSS,但這已超出了基礎(chǔ)討論的范疇。

ssthresh (Slow Start Threshold) 的確定

與 MSS 不同,ssthresh 是 TCP 發(fā)送方 內(nèi)部維護 的一個狀態(tài)變量,它不對外宣告,也無需協(xié)商。它的作用是作為慢啟動和擁塞避免兩種模式的切換“警戒線”。

初始值: 在一個 TCP 連接剛剛建立時,發(fā)送方對網(wǎng)絡(luò)路徑的狀況一無所知。因此,ssthresh 通常會被設(shè)置為一個 非常大 的值(實際上是系統(tǒng)允許的最大接收窗口大小)。這樣做是為了讓“慢啟動”階段可以盡可能地發(fā)揮作用,不受限制地進行指數(shù)增長,直到第一次擁塞事件發(fā)生。

動態(tài)更新:ssthresh 的值在連接的整個生命周期中是動態(tài)變化的,其更新遵循一個核心原則: 當擁塞發(fā)生時,將 ssthresh 設(shè)置為當前擁塞窗口 cwnd 的一半 。

  • 更精確地說,是 ssthresh = max(FlightSize / 2, 2 * MSS)FlightSize 指的是已發(fā)送但未被確認的數(shù)據(jù)量,在大多數(shù)情況下約等于 cwnd
  • 與 2 * MSS 取較大值的目的是為了防止 ssthresh 變得過小,導(dǎo)致網(wǎng)絡(luò)性能低下。

ssthresh 的本質(zhì)是 TCP 的一種“記憶”: 它記錄了上一次網(wǎng)絡(luò)擁塞發(fā)生時窗口大小的一半,作為下一次探測網(wǎng)絡(luò)容量時的“安全”起點 。

TCP 擁塞控制實戰(zhàn):一個完整例子的剖析

理論總是有些枯燥,讓我們通過一個生動的例子,從頭到尾觀察一個 TCP 連接的 cwnd 是如何在各種算法的支配下動態(tài)變化的。

場景設(shè)定:

  • 客戶端 A 向服務(wù)器 B 發(fā)送一個大文件。
  • 我們假設(shè) MSS = 1 KB,方便計算。
  • 連接剛建立,初始擁塞窗口 cwnd = 2 MSS (即 2 KB)。
  • 初始慢啟動閾值 ssthresh 非常大 (例如 64 KB),在開始階段不會限制 cwnd 的增長。

第 1 階段:慢啟動 (Slow-Start)

連接開始,TCP 首要任務(wù)是快速探明網(wǎng)絡(luò)容量。

  • RTT 0:cwnd = 2 KB。A 發(fā)送 2 個數(shù)據(jù)包。
  • RTT 1: A 收到 2 個 ACK。根據(jù)慢啟動規(guī)則(每收到一個 ACK,cwnd 增加 1 MSS),cwnd 變?yōu)?nbsp;2 KB + 2 * 1 KB = 4 KB。A 現(xiàn)在可以發(fā)送 4 個數(shù)據(jù)包。
  • RTT 2: A 收到 4 個 ACK。cwnd 變?yōu)?nbsp;4 KB + 4 * 1 KB = 8 KB
  • RTT 3: A 收到 8 個 ACK。cwnd 變?yōu)?nbsp;8 KB + 8 * 1 KB = 16 KB
  • RTT 4: A 收到 16 個 ACK。cwnd 變?yōu)?nbsp;16 KB + 16 * 1 KB = 32 KB

cwnd 的增長軌跡是 2 -> 4 -> 8 -> 16 -> 32,這是典型的指數(shù)增長。假設(shè)我們的 ssthresh 初始值就是 32 KB。現(xiàn)在 cwnd 達到了 ssthresh,慢啟動階段結(jié)束。

第 2 階段:擁塞避免 (Congestion Avoidance)

cwnd 已經(jīng)到達了一個相對合理的水平,不能再野蠻增長了,需要進入謹慎的線性探測階段。

  • RTT 5:cwnd = 32 KB。A 發(fā)送 32 個包并全部收到 ACK。根據(jù)擁塞避免規(guī)則(每輪 RTT 增加 1 MSS),cwnd 變?yōu)?nbsp;32 KB + 1 KB = 33 KB
  • RTT 6:cwnd = 33 KB。一切順利。cwnd 變?yōu)?nbsp;33 KB + 1 KB = 34 KB
  • ... 這個過程持續(xù)進行,cwnd 緩慢增加。
  • RTT n: 假設(shè)當 cwnd 增長到 40 KB 時,網(wǎng)絡(luò)開始出現(xiàn)擁塞,A 發(fā)送的 40 個包中有一個不幸丟失了。

第 3 階段:擁塞事件 - 三次重復(fù)確認 (Reno 模式)

接收方 B 沒有收到丟失的包,但收到了它后面的一些包。于是 B 不斷地對最后一個收到的、有序的包發(fā)送重復(fù) ACK。很快,A 收到了三次重復(fù)的 ACK。

  • 擁塞信號: 三次重復(fù)確認。這被認為是輕度擁塞的信號。
  • 觸發(fā)機制: 快速重傳 (Fast Retransmit) 與快速恢復(fù) (Fast Recovery)。
  • 變量變化:
  1. A 立即重傳丟失的那個包,不等待超時。
  2. ssthresh 被更新為當前 cwnd 的一半:ssthresh = 40 KB / 2 = 20 KB。這是新的“慢啟動警戒線”。
  3. cwnd 不再降為 1,而是直接設(shè)置為新的 ssthresh 值:cwnd = 20 KB
  4. TCP 直接進入 擁塞避免 階段。

第 4 階段:新一輪的擁塞避免

A 從 cwnd = 20 KB 開始,繼續(xù)進行線性的加性增窗。

  • RTT n+1:cwnd = 20 KB。發(fā)送 20 個包,一切順利。cwnd 變?yōu)?nbsp;20 KB + 1 KB = 21 KB
  • RTT n+2:cwnd = 21 KBcwnd 變?yōu)?nbsp;21 KB + 1 KB = 22 KB
  • ... cwnd 再次緩慢爬升。

第 5 階段:嚴重擁塞事件 - 超時 (Timeout)

假設(shè)當 cwnd 增長到 26 KB 時,網(wǎng)絡(luò)發(fā)生了嚴重的擁塞,A 發(fā)送的一個數(shù)據(jù)包及其重傳包都丟失了,導(dǎo)致 A 在規(guī)定時間內(nèi)沒有收到任何 ACK,觸發(fā)了 超時 (Timeout) 。

  • 擁塞信號: 超時。這被認為是嚴重擁塞的信號。
  • 變量變化:
  1. ssthresh 更新為當前 cwnd 的一半:ssthresh = 26 KB / 2 = 13 KB
  2. cwnd 被無情地重置為初始值:cwnd = 2 KB
  3. TCP 重新進入 慢啟動 階段。

TCP Congestion Control 經(jīng)典圖例:

圖片圖片

解惑:ACK 時鐘:TCP 如何感知“一輪” RTT?

TCP 沒有 一個精確的“RTT 時間窗”來框定“這一輪”的 ACK。它依賴于一個更為優(yōu)雅和強大的機制—— ACK 時鐘 (ACK Clocking) 。

核心思想:事件驅(qū)動,而非時間驅(qū)動

首先要明確,TCP 的擁塞控制算法不是基于一個固定的計時器去判斷“一輪 RTT 是否結(jié)束”。它是一個 事件驅(qū)動 的系統(tǒng),這個核心事件就是 收到 ACK 。

這個機制被稱為“自時鐘 (Self-clocking)”。可以這樣理解:

  1. 發(fā)送方將一個窗口的數(shù)據(jù)包(例如 cwnd 個)發(fā)送到網(wǎng)絡(luò)中。
  2. 這些數(shù)據(jù)包在網(wǎng)絡(luò)中傳輸,經(jīng)過路由、排隊,最終到達接收方。
  3. 接收方在收到數(shù)據(jù)后,會返回 ACK。
  4. 這些 ACK 同樣需要經(jīng)過網(wǎng)絡(luò)傳輸才能回到發(fā)送方。
  5. 關(guān)鍵在于: 發(fā)送方只有在收到一個“舊”數(shù)據(jù)包的 ACK 后,才被允許發(fā)送一個“新”的數(shù)據(jù)包。

ACK 返回的速率,從根本上決定了發(fā)送方發(fā)送新數(shù)據(jù)的速率。如果網(wǎng)絡(luò)通暢,ACK 回來得快,發(fā)送方的“時鐘”就走得快,數(shù)據(jù)發(fā)送也快。如果網(wǎng)絡(luò)擁塞,ACK 回來得慢,發(fā)送方的“時鐘”自然就慢下來了,數(shù)據(jù)發(fā)送也隨之減速。

如何實現(xiàn)“每輪 RTT”的規(guī)則?

既然沒有精確的 RTT 時間窗,那“每輪 RTT 增加 1 MSS”這種規(guī)則是如何實現(xiàn)的呢?

TCP 將“ 成功接收到一個 cwnd 大小數(shù)據(jù)的 ACK ”近似地看作“ 經(jīng)過了一輪 RTT ”。

讓我們回到擁塞避免的例子:

  • 假設(shè) cwnd = 32 KBMSS = 1 KB。這意味著發(fā)送方在一個“RTT 周期”內(nèi),期望收到 32 個數(shù)據(jù)包的 ACK。
  • “每輪 RTT 增加 1 MSS”的目標,就被分解到了這 32 個 ACK 事件上。
  • 每當收到一個 ACK,cwnd 就增加一小部分:1 MSS / 32
  • 當所有 32 個 ACK 都順利返回時,cwnd 的總增量正好是 32 * (1 MSS / 32) = 1 MSS
  • 這正是 cwnd += MSS * MSS / cwnd 公式(當 cwnd 以字節(jié)為單位時)的直觀體現(xiàn)。

結(jié)論就是: TCP 不去“判斷”一輪的 ACK 是否全部收到了,而是通過一個 平滑、累加 的方式,將宏觀的“每輪 RTT”的目標,分解到微觀的“每一次 ACK 到達”的事件上。ACK 的到達自然地驅(qū)動著窗口的增長,構(gòu)成了 TCP 擁塞控制算法的脈搏。

解惑:詳解快速重傳與快速恢復(fù)

這兩個機制是 TCP Reno 相對于 TCP Tahoe 的核心改進,它們緊密協(xié)作,旨在更智能地處理輕度網(wǎng)絡(luò)擁塞。

快速重傳 (Fast Retransmit):擁塞的“哨聲”

快速重傳是一種 丟包檢測 機制。它的核心思想是,如果發(fā)送方連續(xù)收到了 三個或以上 的重復(fù) ACK(例如,都要求確認同一個序列號),那么 TCP 就有充分的理由相信,這個序列號對應(yīng)的數(shù)據(jù)包已經(jīng)在網(wǎng)絡(luò)中丟失了。

為什么是三次? 網(wǎng)絡(luò)中的數(shù)據(jù)包有時會因為路由變化等原因發(fā)生 亂序 。收到一兩個重復(fù)的 ACK 可能是由于亂序到達引起的,但收到三個就說明后續(xù)的數(shù)據(jù)包大概率已經(jīng)到達,而中間的那個包丟失的可能性極高。

一旦觸發(fā)快速重傳,發(fā)送方會 立即重傳 那個被認為丟失的數(shù)據(jù)包,而 不必等待超時計時器 (RTO) 到期 。這就是“快速”的含義。它大大縮短了因丟包而造成的傳輸中斷時間。

快速恢復(fù) (Fast Recovery):擁塞后的“手術(shù)刀”

快速恢復(fù)是一個 擁塞控制 策略。它在快速重傳被觸發(fā)后 立即啟動 。

它做什么?(Reno 的經(jīng)典流程)

  1. 進入狀態(tài): 當快速重傳觸發(fā)時,TCP 進入快速恢復(fù)狀態(tài)。
  2. 執(zhí)行操作:
  • 將 ssthresh 設(shè)置為當前 cwnd 的一半(ssthresh = cwnd / 2)。這步操作被稱為“乘性減窗 (MD)”。
  • 將 cwnd 也直接設(shè)置為新的 ssthresh 值(cwnd = ssthresh)。
  • 注意: 與 Tahoe 不同,cwnd 沒有降為 1,并且跳過了慢啟動。
  1. 維持與退出: TCP 會一直 保持 在快速恢復(fù)狀態(tài),直到收到一個 新的 ACK (即確認了被重傳數(shù)據(jù)的 ACK)。收到這個新 ACK 后,TCP 就會 退出快速恢復(fù) 狀態(tài),并進入標準的 擁塞避免 階段。

存在退出快速恢復(fù)的說法嗎? “快速恢復(fù)”是 TCP 的一個明確的 狀態(tài) 。TCP 在進入這個狀態(tài)后,會執(zhí)行一系列特殊的操作,直到某個條件滿足后才會 退出 該狀態(tài)。

TCP 擁塞控制的演進史

TCP 擁塞控制不是一蹴而就的,而是經(jīng)歷了幾十年的發(fā)展和迭代。其中最重要的幾個版本是 Tahoe、Reno 和 NewReno。

TCP Tahoe (1988) - 開創(chuàng)者

為了解決 1980 年代末期的“擁塞崩潰”問題,TCP Tahoe 首次引入了完整的擁塞控制機制:

  • 核心機制 :同時包含了慢啟動和擁塞避免 (AIMD)。
  • 丟包檢測 :通過兩種方式推斷丟包:

超時 (Timeout) :發(fā)送數(shù)據(jù)后在規(guī)定時間內(nèi)未收到 ACK。

三次重復(fù)確認 (Triple Duplicate ACKs) :連續(xù)收到三個相同的 ACK,表明接收方收到了后續(xù)的數(shù)據(jù)包,但中間有一個包丟失了。

  • 策略 :無論是由超時還是由三次重復(fù)確認檢測到丟包,Tahoe 的處理方式都非常“激進”:

將 ssthresh 設(shè)置為當前 cwnd 的一半。

將 cwnd 重置為 1 個 MSS。

重新進入 慢啟動 階段。

這種“一刀切”的方式雖然有效,但在網(wǎng)絡(luò)只是輕微擁塞(例如只丟了一個包)時,將 cwnd 降至 1 會導(dǎo)致吞吐量的巨大抖動。

TCP Reno (1990) - 優(yōu)化者

TCP Reno 在 Tahoe 的基礎(chǔ)上進行了重要優(yōu)化,它認為“三次重復(fù)確認”和“超時”是兩種不同程度的擁塞信號。

  • 快速重傳 (Fast Retransmit) :當收到三次重復(fù)確認時,Reno 不再等待超時,而是立即重傳丟失的那個數(shù)據(jù)段。
  • 快速恢復(fù) (Fast Recovery) :這是 Reno 的精髓。在執(zhí)行快速重傳后,Reno 不會 將 cwnd 降至 1,而是:

將 ssthresh 設(shè)置為當前 cwnd 的一半。

將 cwnd 直接設(shè)置為新的 ssthresh 值(而不是 1)。

直接進入 擁塞避免 階段(加性增長),跳過了慢啟動。

這種機制使得在發(fā)生單個丟包時,TCP 的吞吐量下降得不那么劇烈,恢復(fù)得也更快。只有在發(fā)生更嚴重的“超時”事件時,Reno 才會像 Tahoe 一樣將 cwnd 降至 1 并重新開始慢啟動。

TCP NewReno (1996) - 完善者

TCP Reno 在處理單個窗口內(nèi)發(fā)生 多個丟包 的情況時表現(xiàn)不佳。當?shù)谝粋€丟失的包被重傳并確認后,Reno 就會退出快速恢復(fù)狀態(tài),但此時窗口內(nèi)可能還有其他丟失的包,這會導(dǎo)致吞-吐量的多次劇烈下降。

TCP NewReno 優(yōu)化了快速恢復(fù)算法,使其能夠更好地處理單個窗口內(nèi)的多個丟包事件,從而提高了網(wǎng)絡(luò)傳輸?shù)姆€(wěn)定性和效率。

Reno 的“快速恢復(fù)”有一個致命缺陷:它只能很好地處理單個窗口內(nèi)的 一次 丟包。如果一個窗口內(nèi)有多個包丟失了,Reno 就會“精神錯亂”。

Reno 的問題場景:

  1. 假設(shè)發(fā)送方在一個窗口內(nèi)發(fā)送了 10 個包(#1 到 #10)。其中 #3 和 #5 都丟了。
  2. 接收方收到 #1, #2, #4。于是不斷發(fā)送針對 #2 的重復(fù) ACK。
  3. 發(fā)送方收到三次重復(fù) ACK,觸發(fā)快速重傳,重傳 #3,并進入快速恢復(fù)(cwnd 減半)。
  4. 假設(shè)重傳的 #3 成功到達。接收方現(xiàn)在可以確認到 #4 了,于是發(fā)回一個對 #4 的新 ACK。
  5. 問題來了: Reno 收到這個新的 ACK (被稱為部分 ACK,因為它沒有確認所有已發(fā)送的數(shù)據(jù)) 時,會錯誤地認為網(wǎng)絡(luò)擁塞已經(jīng)解除,于是 立即退出快速恢復(fù) 狀態(tài),并將 cwnd 設(shè)置回 ssthresh 。
  6. 但實際上 #5 仍然是丟失的!很快,發(fā)送方又會收到針對 #4 的重復(fù) ACK,不得不再次觸發(fā)快速重傳和快速恢復(fù),導(dǎo)致 cwnd 再一次減半。這使得吞吐量恢復(fù)得非常慢。

NewReno 的優(yōu)化:

  • NewReno 在收到部分 ACK 時, 不會立即退出快速恢復(fù) 。
  • 它會判斷出“哦,我重傳的包被確認了,但對方?jīng)]有確認到最新的數(shù)據(jù),這說明窗口里肯定還有別的包也丟了”。
  • 于是,NewReno 會立即重傳它推斷出的下一個丟失的包(在這個例子里是 #5),并 保持在快速恢復(fù)狀態(tài) ,直到所有在進入該狀態(tài)時“在途”的數(shù)據(jù)包都被確認為止。
  • 這樣,NewReno 用一次快速恢復(fù)過程,解決了單個窗口內(nèi)的多次丟包問題,避免了 cwnd 的多次懲罰性下降。

下面是一個簡單的對比表格:

事件

TCP Tahoe 的響應(yīng)

TCP Reno / NewReno 的響應(yīng)

超時 (Timeout)

ssthresh = cwnd/2

cwnd = 1, 進入慢啟動

ssthresh = cwnd/2

cwnd = 1, 進入慢啟動

三次重復(fù)確認

ssthresh = cwnd/2

cwnd = 1, 進入慢啟動

ssthresh = cwnd/2

cwnd = ssthresh, 進入 擁塞避免

總結(jié)與展望

TCP 擁塞控制是互聯(lián)網(wǎng)能夠穩(wěn)定運行的基石之一,它體現(xiàn)了分布式系統(tǒng)中簡單而強大的設(shè)計哲學(xué)。其核心目標可以總結(jié)為:

  • 高吞吐量 (High Throughput) :高效利用網(wǎng)絡(luò)資源。
  • 公平性 (Fairness) :確保不同數(shù)據(jù)流能公平共享帶寬。
  • 快速響應(yīng) (Responsiveness) :快速適應(yīng)網(wǎng)絡(luò)條件的變化。
  • 分布式控制 (Distributed Control) :無需中央?yún)f(xié)調(diào),易于擴展。

從 Tahoe 的誕生,到 Reno 和 NewReno 的不斷完善,TCP 擁塞控制的核心思想——基于丟包信號的 AIMD——在很長一段時間內(nèi)都主導(dǎo)著互聯(lián)網(wǎng)。

然而,時代在進步。在當今高帶寬、高延遲(長肥網(wǎng)絡(luò))和無線網(wǎng)絡(luò)環(huán)境下,僅依賴丟包作為擁塞信號已顯不足。因此,更新的擁塞控制算法,如基于延遲的 TCP Vegas 、Google 開發(fā)的 BBR (Bottleneck Bandwidth and Round-trip propagation time) 以及目前 Linux 系統(tǒng)默認的 CUBIC,正在不斷涌現(xiàn)和部署,以適應(yīng)更加復(fù)雜的網(wǎng)絡(luò)環(huán)境。

但無論技術(shù)如何演進,理解 TCP Tahoe 和 Reno 所奠定的基礎(chǔ),依然是每一位網(wǎng)絡(luò)學(xué)習(xí)者和工程師的必修課。

責任編輯:武曉燕 來源: Piper蛋窩
相關(guān)推薦

2025-09-01 04:00:55

2025-08-26 02:50:00

2025-09-01 07:08:43

2025-08-26 00:38:48

2025-08-27 06:29:45

2025-08-29 06:24:37

2025-09-01 01:22:00

2025-02-25 08:16:43

2013-05-14 13:02:17

計算機網(wǎng)絡(luò)基礎(chǔ)協(xié)議

2013-03-08 12:51:03

計算機網(wǎng)絡(luò)基礎(chǔ)協(xié)議DHCP

2024-03-28 11:32:38

計算機網(wǎng)絡(luò)集線器連接設(shè)備

2010-09-02 16:02:45

計算機網(wǎng)絡(luò)協(xié)議

2010-09-08 20:45:31

計算機網(wǎng)絡(luò)協(xié)議

2010-06-12 16:56:37

2010-09-08 20:42:09

計算機網(wǎng)絡(luò)協(xié)議

2015-07-15 11:14:42

2010-06-14 18:58:52

VoIP計算機網(wǎng)絡(luò)協(xié)議

2010-09-08 20:53:14

WinPCap計算機網(wǎng)絡(luò)協(xié)議

2015-05-28 11:09:00

2010-06-13 15:08:07

計算機網(wǎng)絡(luò)協(xié)議
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 上栗县| 巴东县| 武威市| 孟津县| 和静县| 都匀市| 逊克县| 海晏县| 兰西县| 安徽省| 松滋市| 岚皋县| 古浪县| 门头沟区| 团风县| 德阳市| 海南省| 东山县| 靖安县| 绥芬河市| 民丰县| 葵青区| 周口市| 峨眉山市| 富顺县| 西林县| 阿城市| 高阳县| 卫辉市| 阿图什市| 巫山县| 浑源县| 肇庆市| 邢台县| 邻水| 娄烦县| 吉首市| 贞丰县| 黄陵县| 南和县| 贡山|