Skip to content

5.1 TCP 的拥塞控制

:material-circle-edit-outline: 约 2387 个字 :material-clock-time-two-outline: 预计阅读时间 8 分钟

TCP 的拥塞控制

PPT

什么是拥塞

在某段时间,若对网络中某资源的 需求超过了所能提供的可用部分,网络的性能就要明显变坏,整个网络的吞吐量将随输入负荷的增大而下降

这种现象称为拥塞 (congestion),最坏结果:系统崩溃

[!IMPORTANT]

增加资源不能解决拥塞,而且还可能使网络的性能更坏,例如:

  1. 拥塞引起的重传并不会缓解网络的拥塞,反而会加剧网络的拥塞
  2. 提高处理机处理的速率会将瓶颈转移到其他地方

[!NOTE]

拥塞控制与流量控制的区别

拥塞控制是防止过多的数据注入到网络中,避免网络中的路由器或链路过载,是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络传输性能有关的所有因素。

流量控制是抑制发送端发送数据的速率,以使接收端来得及接收,是点对点通信量的控制,是个端到端的问题

拥塞控制的一般原理

拥塞控制的前提:网络能够承受现有的网络负荷。

分组的丢失是网络发生拥塞的征兆,而不是原因

在许多情况下,甚至正是拥塞控制本身成为引起网络性能恶化、甚至发生死锁的原因

开环控制和闭环控制

开环控制:在设计网络时,事先考虑周全,力争避免发生拥塞

闭环控制:在发生拥塞后,采取措施进行控制,消除拥塞

TCP 的拥塞控制方法

TCP 采用基于滑动窗口的方法进行拥塞控制,属于闭环控制方法。

TCP 发送方维持一个 拥塞窗口 cwnd (Congestion Window)

拥塞窗口的大小取决于网络的拥塞程度,是动态变化的

真正的发送窗口值 = Min (接收方通知的窗口值,拥塞窗口值)

发送方判断拥塞的方法:隐式反馈

  • 超时重传计时器超时:网络已经出现了拥塞
  • 收到 3 个重复的确认:预示网络可能会出现拥塞。

因此,发送方 在超时重传计时器启动时,就判断网络出现了拥塞。

TCP 拥塞控制算法

慢开始 (Slow start)

目的:探测网络的负载能力或拥塞程度。

由小到大逐渐增大注入到网络中的数据字节,即:由小到大逐渐增大拥塞窗口数值。

2 个控制变量

  • 拥塞窗口 cwnd
  • 慢开始门限 ssthresh
    • 当 cwnd < ssthresh 时,使用慢开始算法。
    • 当 cwnd > ssthresh 时,停止使用慢开始算法,改用拥塞避免算法
    • 当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞避免算法。

在每收到一个对新的报文段的确认,就把 cwnd 增加 \(\le\) 1 SMSS (Sender Maximum Segment Size) 的数值,即 min (N, SMSS)

image-20241214114914833

一个 传输轮次(transmission round) 所经历的时间其实就是往返时间 RTT

例如:拥塞窗口 cwnd = 4,这时的往返时间 RTT 就是发送方连续发送 4 个报文段,并收到这 4 个报文段的确认,总共经历的时间。

image-20241214114923838

拥塞避免

[!NOTE]

拥塞避免并非完全避免拥塞,而是让拥塞窗口增长得缓慢些,使网络不容易出现拥塞

目的:让拥塞窗口 cwnd 缓慢地增大,避免出现拥塞

每经过一个往返时间 RTT(不管在此期间收到了多少确认),发送方的拥塞窗口 cwnd = cwnd + 1

具有加法增大 AI (Additive Increase) 特点:使拥塞窗口 cwnd 按线性规律缓慢增长

image-20241214120203697

无论在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(重传定时器超时):

  1. ssthresh = max (cwnd/2,2)
  2. cwnd = 1
  3. 执行慢开始算法

目的:迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。

[!EXAMPLE] 慢开始和拥塞避免算法的实现

image-20241214120754214

TCP 连接进行初始化时,拥塞窗口置为 1(窗口单位不使用字节而使用报文段)

将慢开始门限的初始值设置为 16 个报文段,即 ssthresh = 16。

开始执行慢开始算法时,拥塞窗口 cwnd = 1,发送第一个报文段。

发送方每收到一个对新报文段的确认 ACK,就把拥塞窗口值加 1,因此拥塞窗口 cwnd 随着往返时延 RTT 按指数规律增长。

当拥塞窗口 cwnd 增长到慢开始门限值 ssthresh 时,改为执行拥塞避免算法,拥塞窗口按线性规律增长(即图中标号 1 的位置)

当拥塞窗口 cwnd = 24 时,网络出现了超时,发送方判断为网络拥塞。调整门限值 ssthresh = cwnd / 2 = 12,同时设置拥塞窗口 cwnd = 1,进入慢开始阶段(即图中标号 2 的位置)

快重传 FR (Fast Retransmission)

目的:让发送方尽早知道发生了个别报文段的丢失。

发送方只要连续收到三个重复的确认,就立即进行重传(即“快重传”),这样就不会出现超时。

接收方即使收到了失序的报文段,也要立即发出对已收到的报文段的重复确认。

image-20241214123039374

快恢复 FR (Fast Recovery)

当发送端收到连续三个重复的确认时,不执行慢开始算法,而是执行快恢复算法 FR (Fast Recovery) 算法

  1. 慢开始门限 ssthresh = 当前拥塞窗口 cwnd / 2 ;
  2. 乘法减小 MD (Multiplicative Decrease) 拥塞窗口,新拥塞窗口 cwnd = 慢开始门限 ssthresh
  3. 执行拥塞避免算法,使拥塞窗口缓慢地线性增大(加法增大 AI)

二者合在一起就是所谓的 AIMD 算法,使 TCP 性能有明显改进。

[!EXAMPLE] 快重传和快恢复算法

image-20241214123238069

当拥塞窗口 cwnd = 16 时,发送方连续收到 3 个对同一个报文段的重复确认(记为 3-ACK)。发送方改为执行快重传和快恢复算法。

执行快重传和快恢复算法:发送方调整门限值 ssthresh = cwnd / 2 = 8,设置拥塞窗口 cwnd = ssthresh = 8,开始执行拥塞避免算法。

TCP 拥塞控制流程图

image-20241214123312937

发送窗口的上限值 = Min [rwnd, cwnd]

  • 当 rwnd < cwnd 时,是接收方的接收能力限制发送窗口的最大值。
  • 当 cwnd < rwnd 时,是网络拥塞限制发送窗口的最大值。

主动队列管理 AQM

TCP 拥塞控制和网络层采取的策略有密切联系,其中对 TCP 拥塞控制影响最大的就是路由器的分组丢弃策略

“先进先出”FIFO 处理规则

在最简单的情况下,路由器队列通常采用先进先出 (FIFO) 处理规则与尾部丢弃策略 (tail-drop policy)。

当队列已满时,以后到达的所有分组将都被丢弃。

分组丢弃使发送方出现 超时重传,使 TCP 连接进入慢开始状态。

image-20241214124401950

主动队列管理 AQM (Active Queue Management)

不要等到路由器的队列长度已经达到最大值时才不得不丢弃后面到达的分组,而是在队列长度达到某个值得警惕的数值时(即当网络拥塞有了某些拥塞征兆时),就主动丢弃到达的分组。

AQM 可以有不同实现方法,其中曾流行多年的就是 随机早期检测 RED (Random Early Detection)

路由器队列维持两个参数:队列长度最小门限 THmin 队列长度最大门限 THmax

RED 对每一个到达的分组都先计算平均队列长度 \(L_{AV}\)

  • \(L_{AV} < Th_{min}\),则将新到达的分组放入队列进行排队,即丢弃概率 p = 0
  • \(L_{AV} > Th_{min}\) ,则将新到达的分组丢弃,即丢弃概率 p = 1
  • 若 $Th_{min} \le L_{AV} \le Th{max} $,丢弃概率 p: 0 < p < 1

image-20241214124648525

TCP 的运输连接管理

TCP 是面向连接的协议,有三个阶段:连接建立,数据传送,连接释放

TCP 的连接管理就是使 TCP 连接的建立和释放都能正常地进行

TCP 的连接建立(不需要记忆细节,理解即可)

TCP 建立连接的过程叫做 握手

采用 三报文握手:在客户和服务器之间交换三个 TCP 报文段,以防止已失效的连接请求报文段突然又传送到了,因而产生 TCP 连接建立错误

image-20241214125116735

  1. B 的 TCP 服务器进程先创建传输控制块 TCB,准备接受客户进程的连接请求。
  2. A 的 TCP 向 B 主动发出连接请求报文段,其首部中的同步位 SYN = 1,并选择序号 seq = x,表明传送数据时的第一个数据字节的序号是 x。
    • 注意:TCP 规定,SYN 报文段(即 SYN = 1 的报文段)不能携带数据,但要消耗掉一个序号。
  3. B 的 TCP 收到连接请求报文段后,如同意,则发回确认。B 在确认报文段中应使 SYN = 1,使 ACK = 1,其确认号 ack = x + 1,自己选择的序号 seq = y。
    • 这个报文段也不能携带数据,但同样要消耗掉一个序号。
  4. A 收到此报文段后向 B 给出确认,其 ACK = 1,确认号 ack = y + 1,可以带数据
    • A 的 TCP 通知上层应用进程,连接已经建立
  5. B 的 TCP 收到主机 A 的确认后,也通知其上层应用进程:TCP 连接已经建立。双方可以开始数据传送。

TCP 的连接释放(不需要记忆细节,理解即可)

数据传输结束后,通信的双方都可释放连接,释放过程是四报文握手

image-20241214125601981

  1. A 的应用进程先向其 TCP 发出连接释放报文段,并停止再发送数据,主动关闭 TCP 连接。A 把连接释放报文段首部的 FIN = 1,其序号 seq = u,等待 B 的确认。
  2. B 发出确认,ACK = 1,确认号 ack = u+1,这个报文段的序号 seq = v。TCP 服务器进程通知高层应用进程。
  3. 若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP 释放连接。FIN = 1,ACK = 1,确认号 ack = u+1。
  4. A 收到连接释放报文段后,必须发出确认。 ACK = 1,确认号 ack = w+1,自己的序号 seq = u + 1
    • 请注意:此时 TCP 连接还没有释放掉。必须经过时间等待计时器 (TIME-WAIT timer) 设置的时间 2MSL 后,A 才释放 TCP 连接。
    • 第一,保证发送的最后一个 ACK 报文段能够到达 B。第二,防止“已失效的连接请求报文段”出现在本连接中。

TCP 的有限状态机

image-20241214130349146