---
# System prepended metadata

title: 網路是怎樣連接的(九)TCP的性能優化(下)
tags: [計算機網路, ' TCP']

---

---
creator: Zach
tags: 計算機網路, TCP
created: 2021-10-15 
---
# 網路是怎樣連接的(九)TCP的性能優化(下)
## 思考重點
- 流量控制的原理以及實現目的?
- 壅塞控制的原理以及實現目的?
## 核心知識

![](https://i.imgur.com/kvCTpTX.png)
<center>核心知識點</center>

## 流量控制
流量控制的目的在上一篇中有提到，是為了防止接收方大量且無節制的接收封包，換言之就是避免接收方處理不及產生超負荷，或者漏接封包等，這些問題可能會觸發接收方進行丟包處理，讓本來就很嚴重的網路狀況火上加油

因此流量控制的重點在於接收方的**處理能力**。TCP會在頭部提供視窗大小的欄位，接收方可以依照當前緩衝區內可用的記憶體來決定視窗大小。當應用程式向緩衝區拿取數據的速率大於封包到達的速率時，視窗大小就會變大，相反的若接收速率大於應用程式的處理速率，則會造成緩衝區大小縮減，視窗大小這時就會向下修正。接收方可以藉由更改視窗大小欄位，並透過ACK響應告訴發送方，我現在處理封包的上限有多大
</BR>

![](https://i.imgur.com/NorASn6.png)
<center>接收視窗</center>
</BR>

接收方配置的緩衝區示意圖如上所示，封包到達緩衝區後接收方的應用程式通常不會馬上向其拿取數據，因為它自己也忙於其他事情，因此當前緩衝區處在一個只進不出的狀態，這時候接收方會藉由調整指向已接收並確認封包指標位置來進行視窗滑動，這個滑動視窗的大小就是流量控制視窗大小。視窗大小的長度必須**小於等於**緩衝區總長，端看接收方的處理消息能力
>可以試著聯想這種場景，有一間非常有名的餐廳一次最多只能有效處理10名顧客的點餐，而整個餐廳總共可以容納100人，若是進餐廳的人控制在10人以內，那麼就可以很好的消化排隊人潮，反之假如進餐廳的人數太多就必須在餐廳門口限制進店人數，好讓店員能夠有效處理人流。進店人數限制相當於視窗大小，店員相當於接收方處理能力，餐廳容納人數相當於緩衝區大小
</BR>

![](https://i.imgur.com/EHFXbeo.png)
<center>流量控制</center>
</BR>
為了提高整體效率，我們將結合滑動視窗與流量控制，首先我們會先試探性地發送一個封包來確認視窗大小，得到接收方響應後就可以依照響應頭部的window標誌位來設定雙方的視窗大小，我們都知道流量控制的內涵是根據接收方的處理速度來調整封包傳送數量，不過視窗大小的調整時機到底該如何判斷?

視窗大小更新的主要時機是**應用程式**向緩衝區拿取數據以及緩衝區已滿。也就是說接收方不會在每次響應中更變視窗大小，一來在每次接收封包過程中都需要處理視窗大小的判斷太浪費效率，二來接收方應用程式不會在每次收到封包會就*準時*向緩衝區拿取數據

真實的操作情況是，接收方不會每接收一個封包就發布一次更新響應，而是會等待一段時間，看看當前是否有其他通知，例如更新或者新的封包接收等，不僅可以將響應封包與視窗更新結合在一起節省響應封包數量，也可以在需要連續發布響應時減少響應次數，如同我們在[接收方響應丟失](https://hackmd.io/@Zacch/r1gbrHLrY)中介紹，TCP可以根據最後接收到的響應判斷前面的封包接成功被接收方接收

假若接收方連續收到封包後，應用程式依然沒有從緩衝區中拿取數據，這時的緩衝區呈現爆滿狀態，也就是滑動視窗根本沒有移動的空間，**指向下一個封包的指標與緩衝區邊界重疊**，接收方必須通知發送方視窗大小為0的響應。對於發送方來說，它沒有收到封包的響應確認，所以視窗不會移動，再來接收到視窗大小為0的更新後更是把整個滑動視窗的機制*鎖住*

接收到視窗大小為0的發送方會貼心地等待接收方處理緩衝區數據，並回傳一個視窗更新通知，不過它的耐心也是有極限就對了。通常接收方系統會設定一個逾時重傳時間，若超過時間內沒有收到更新消息，就立刻發送一個資料長度為1 byte的探索封包，向接收方詢問緩衝區大小，為了防止返回更新視窗大小的響應遺失，接收方必須時刻準備探索封包的發送，不然整個收發流程將會無法繼續進行

## 壅塞控制
TCP可以透過滑動視窗來增加封包的發送效率，但也衍生了網路壅塞問題。封包在網路核心中透過路由器傳遞過程中可能遭遇排隊延遲，逾時、封包丟失等情形，為了避免發送方在網路壅塞時還使用滑動視窗發布大量封包，TCP會在發送第一個封包時使用緩啟動機制，慢慢增加封包發送數量

### 緩啟動
所謂的緩啟動，就是在開始傳送封包時將視窗大小限制成一個最小單位封包(MSS)，如果接收方成功返回響應則將視窗大小增加為2，若連續發送兩個封包也成功返回響應，則將視窗大小增加為4，由此可知壅塞視窗大小是根據封包成功響應後呈**指數**增加，不過是在沒有遇上封包返回逾時的前提下
</BR>

![](https://i.imgur.com/FS9CIe2.png)
<center>緩啟動機制</center>
</BR>

如圖所示，發送方請求從1開始，成功返回響應後便會將滑動視窗提升為當前的2倍，直到到達雙方約定的視窗大小限制為止。除此之外，壅塞控制的一大重點就是壅塞視窗的計算。壅塞視窗是由發送方維護的一個視窗範圍，它會根據當前網路阻塞狀況做出調整，限制發送方視窗

發送方會把接收方給定的視窗大小與壅塞視窗大小做比對，**取其中的最小值作為發送視窗大小**，也就是說如果接收方可以接受總視窗大小長度為4000，但當前網路狀況只允許傳遞長度為2000的視窗，發送方會依照壅塞視窗的限制將視窗大小設為2000，待網路狀況回穩後再將視窗提升至4000

但是壅塞控制不單單只有指數成長這麼簡單，當封包響應發生逾時或其中的發送封包丟失時，壅塞視窗就會馬上發生變化，也就是說若是沒有發生上述狀況，壅塞視窗會在**合理範圍**內不斷變大。上文提及壅塞視窗是呈現指數性增長，接下來就來看看網路發生阻塞時的壅塞視窗調整

### 壅塞控制流程
![](https://i.imgur.com/KlMFnQl.png)
<center>閥值調整</center>
</BR>

#### 壅塞避免演算法
假設根據流量控制，若雙方約定視窗大小為16，TCP使用滑動視窗進行封包發送，黃色區塊1顯示緩啟動機制的指數疊加過程(1-->4-->8-->16)，假如壅塞視窗超過16，則以16設為發送視窗。當TCP發現封包發送在第4輪發生逾時，會直接將壅塞視窗設定成1，並且設定緩啟動閥值，每當封包到達臨界緩啟動閥值時就會觸發以**線性**方式增長壅塞視窗大小，這個機制稱為壅塞避免演算法

**壅塞避免演算法的操作**
- 將壅塞視窗大小設為1
- 將發生逾時的壅塞視窗大小數除以2，並設定該值為緩啟動閥值
- 一旦超過閥值，改以線性方式疊加封包發送數量

>壅塞視窗一旦超過緩啟動閥值就會以每一輪增加一個封包的方式疊加。舉個例子，假如該次滑動視窗連續發送8個封包，當確實收到8個響應時，會在下一輪將連續發送數量提高到9次，也就是說每收到一個響應增加1/N個封包

因此我們在紅色區塊2中可以發現，壅塞視窗下降到1，在還沒觸及緩啟動閥值前，壅塞視窗依舊以指數方式增加。直到壅塞視窗達到8(16/2)，也就是整個黃色區塊3的變化。當到達緩啟動閥值，如圖綠色區塊4，經由壅塞避免演算法的調教，每一輪成功接收響應，僅增加一個封包的數量，如此一來視窗大小就不會一下增加太快，導致網路壅塞

>如圖所示，當網路狀況不穩時，隨時可能發生逾時。在綠色區塊4過程中，壅塞視窗穩定增加到12，這時卻遇上網路壅塞，於是壅塞避免演算法再次將緩啟動閥值調整至6(12/2)，壅塞視窗降為1

>特別注意黃色區塊6的第16輪發送，當下一輪的指數增加恰巧會超過緩啟動閥值時，則以緩啟動閥值為主，所以壅塞視窗會從8改為6

#### 快速恢復機制
不過話又說回來，上圖的壅塞避免演算法將發生逾時的壅塞視窗除以2，並將壅塞視窗設為1的這些操作是以發生**封包逾時**的前提設定的，也就是說封包返回時間超過TCP設定的RTO時間。但觸發高速重傳時的網路狀況並沒有那麼嚴重，所以這種極端的作法應該要有更好的替代方案

快速回復機制使用快速回復演算法，因為高速重傳還需要另外對接收方發送3個響應封包，代表當時網路壅塞狀況還可以接受。快速恢復演算法對壅塞視窗的調整沒有如壅塞避免演算法那樣強烈，而是會把壅塞視窗改為當前的一半後再加上3

**快速回復演算法的操作**
- 將當前壅塞視窗除以2再加上3(來自接收方的3個響應被收到)
- 緩啟動閥值等於當前視窗大小
- 一旦超過閥值，改以線性方式疊加封包發送數量

![](https://i.imgur.com/tAI6aQ6.png)
<center>快速恢復</center>
</BR>

從上圖可以看出，發送第12輪封包時觸發了高速重傳，發送方接收到三個響應後進入丟失封包重傳，同時將壅塞視窗改成之前的一半，由於先前已接收到三個響應，因此會將逾時視窗再加上3。途中的第13輪壅塞視窗就是12/2+3=9，到此快速恢復結束，發送方壅塞視窗緊接著進入壅塞避免算法，爾後呈現線性方式成長。整個過程比直接將壅塞視窗降到1更為平滑，也更有效率

我們可以發現快速恢復演算法的特色，它會將壅塞視窗設置成較適合的大小，不斷地呈現鋸齒狀的成長，結合高速重傳的特色，能快速對壅塞網路做出調整。不過TCP發生逾時的情況相較之下沒那麼大，還記得TCP會動態調整封包的RTO時間嗎，但若許多客戶端同時大量傳送封包，那就可能造成網路核心發生一連串的排隊甚至丟包

> **Tahoe與Reno版本差別**
> 快速恢復演算法並非TCP壅塞控制必要元素，例如一種舊TCP版本Tahoe，它不管發生逾時重傳或是3個響應的高速重傳，都會將壅塞視窗降為1，然後進入緩啟動。另外一種較新的版本Reno，則混合了兩種方式，當封包響應超過RTO時間發生逾時時，則會啟用將壅塞視窗降為1的機制，相反的，若其中的發送封包遺失造成接收方的高速響應回傳的話，則會啟用快速恢復演算法。從上面的範例可以看出我們介紹的是Reno版本


