白話TCP擁塞控制:運糧的河道堵塞了怎麼辦?

無痕幽雨發表於2018-07-19

出處:白話TCP擁塞控制:運糧的河道堵塞了怎麼辦?

 

注:本文來自哈羅的投稿,老劉做了較大修改。

原文地址:

https://blog.csdn.net/zxm342698145/article/details/80998692

 

張家村碼頭的糧食堆積如山,每天都需要用船運到鎮裡。

 

但是去鎮上有50公里,只有水路可走。

 

一大早,碼頭工人們就開始幹活了, 為了早點幹完收工回家,一船接一船,拼命地傳送糧食。

 

可是這水路不僅僅是張家村在運糧食,白頭村還往外運石頭, 東平村還往外運沙子,大家都拼命地往外發貨物,再加上各式各樣,絡繹不絕的商船、客船, 大家很快就發現,船隻太多,水面出現擁堵,工人們只好等待。

 

工人們想這也不是個事兒,大家圍成一圈,蹲在碼頭上一邊抽菸,一邊商量對策。

 

水路很長,怎麼判斷水面是不是擁堵了呢?

 

新來的小張說道:“我有個辦法,不要一下子發那麼多船過去, 我們來個慢啟動,首先運輸一船糧食過去,船到鎮上以後卸掉糧食馬上返回,如果能在很短的時間內返回,說明水面交通狀況還好,可以繼續搬運糧食。

 

包工頭老李說:“不錯,這個船有檢測水面擁堵狀況的作用。然後呢?”

 

小張說: “接下來搬運2船糧食過去,如果依舊能夠在預定的時間內返回,則繼續搬運3船糧食,每次加一船, 依次類推。”

 

老王在碼頭上幹了好幾年, 他立刻跳了起來:“拉到吧你,這樣太慢了!我提議,加快運輸速度,每次傳送的船隻數量是上一次的兩倍。”

 

也就是說,第一次發一條船,如果在預定時間內返回,第二次發2條船,然後是4條船,8條船!

 

老李說:“不行不行,每次都是之前的兩倍,增長得太快了,大家如果都這麼玩,水路很快就阻塞了。”

 

“我還沒說完,” 老王補充, “為了防止擁塞,我們設定一個閾值(其實就是TCP中的ssthresh),當一次發船數量達到這個數,我們就降低速度,不要翻倍,每次只比上次多發一條船。”

老王一邊說一邊拿了一根木棍在地上畫圖:

 

(點選看大圖)

 

我們把前面的階段叫慢啟動發船階段,後面的階段叫擁塞避免發船階段。

 

大家對老王的方案紛紛叫好,就是它了!

 

只有小張慢悠悠地說:“隨著每次傳送船隻的數量越來越多,水路早晚還是要阻塞的。”

 

“沒事,”老王胸有成竹,“如果阻塞了,我們就回到最初的狀態,從1條船,2條船,4條船......開始,但是,我們也要把閾值ssthresh調整一下,把它變小,嗯,假設上次阻塞時發船的數量是24, 那就把閾值調整為它的一半, 就是12。”

 

(點選看大圖)

 

“不錯,不錯,當水路頻繁阻塞時,這個閾值就會下降得很快,發到水面上的船也會大大減少。” 包工頭老李總結,“我們要不按照這個方案試試?”

 

小張嘴裡嘟囔著:“試試就試試,不過你得和白頭村,東平村他們協調好,大家都得用這個方案才行,要不然我們就吃虧了。”

 

“那是自然!這事我來辦!”老李滿口答應。

 

 

 

故事結束了嗎?其實沒有,老王發明的其實叫做 TCP Tahoe演算法。TCP的擁塞控制還有兩個部分,即快速重傳和快速恢復,這裡再簡單介紹一下。

 

快速重傳比較簡單,用一個圖就可以表示:

 

 

在TCP中,資料都是有序號的,例如M1,M2,M3... 。

 

傳送方發出了M1和M2, 接收方都收到了。

 

但是M3報文丟失了, 接收方沒有收到,隨後它收到了M4,M5,M6, 按照快速重傳的演算法,接收方重複確認M2,讓傳送方知道,M3沒有收到。

 

當傳送方收到3個對M2的重複確認的時候,它就意識到,壞菜了,M3丟了, 這時候不必繼續等待M3設定的重傳計時器到期,立刻重傳M3。

 

統計表明,由於傳送方儘早重傳未被確認的報文段,可以使整個網路吞吐量提高約20%。

 

有了快速重傳,可以改進下故事中的擁塞避免模型了。

 

(點選看大圖)

當傳送端收到三個重複確認的時候,就執行快速重傳演算法,並且把閾值減少。

 

但是這個時候它認為網路很可能沒有發生阻塞, 不用執行慢啟動演算法,而是直接從新閾值開始,線性增大

 

這個演算法稱為TCP Reno版,被很多TCP的實現所採用。

 

(完)

相關文章