壅塞與流量控制

快速恢復(fast recovery)

想像一條繁忙的裝配線少了一個零件。有兩種反應。你可以把整條線停掉、清空一切、然後從頭慢慢重啟——若只是少了一個零件,這就太過頭了。或者你可以讓線繼續動,把缺的零件補進去,只稍微減一點速度。快速恢復(fast recovery)就是 TCP 在快速重傳之後選擇了第二種、合理的反應:不要把煞車踩到死,因為源源不絕的重複 ACK 證明這條路徑還在送達封包。

當快速重傳因三個重複 ACK 觸發時,傳統 TCP(Reno)便進入快速恢復。它不會把壅塞視窗崩落到一個封包(那是逾時的做法),而是把視窗砍半——這是 AIMD 的乘法減小步驟——並把 ssthresh 設為那個砍半後的值。關鍵是,它接著繼續傳送:每多一個重複 ACK,就是又有一個封包離開網路、抵達接收端的證據,於是傳送端被允許送出一個新封包,以維持管線滿載。當被重傳區段的確認終於抵達時,傳送端把視窗縮放到新的 ssthresh,並恢復壅塞避免——全程從未回到慢啟動。

其中的道理微妙卻重要:在一連串抵達的封包之中單獨遺失一個,發出的是輕微壅塞的信號,所以溫和的乘法減小才是對的回應。相對地,重送逾時意味著傳送端完全沒聽到任何回音——可能是嚴重停頓——這才足以正當化退回慢啟動那種更嚴厲的重置。快速恢復就是讓 TCP 平順地滑過尋常、偶發的遺失,與在每次小打嗝就頓挫到近乎停止,這兩者之間的差別。它正是賦予現代 TCP 那種特徵性淺鋸齒、而非深鋸齒崩落的東西。

cwnd 在 80 個封包時,三個重複 ACK 抵達。快速重傳重送遺失的區段;快速恢復把 ssthresh 設為 40、cwnd 設為 40(砍半),而傳送端隨著更多重複 ACK 抵達持續涓滴送出新封包。對照同一個流上的逾時:那會把 cwnd 設為 1,從谷底重啟慢啟動——是深得多、慢得多的下陷。

遇到三重重複 ACK,TCP 僅砍半並維持流動;只有逾時才會逼出退回慢啟動的嚴厲崩落。

快速恢復正是讓「靠重複 ACK 偵測到的遺失」比「逾時」在吞吐量上付出小得多代價的原因。這也是為何單一一次逾時代價如此高昂:TCP 把沉默詮釋為嚴重麻煩而一路潛回慢啟動,而藉由重複 ACK 偵測到的遺失則被當成例行的小顛簸。

又稱
fast recovery phase快速恢復快速復原