网工干货知识

超全学习笔记
当前位置:首页 > 干货知识

用于拥塞控制的慢启动重启算法

更新时间:2026年03月27日   作者:spoto   标签(Tag):

一旦客户端和服务器之间建立了连接,发送方就会以数据包的形式将数据发送给接收方。 如果网络处于拥塞状态,那么数据包就会丢失。 这种情况发生在诸如路由器这样的中间设备的缓冲区被填满时。 TCP发送方需要检测其是否已经填满了中间设备的“缓冲区”。如果确实如此,那么就需要降低传输速率,这样网络才能从“拥塞状态”中恢复过来。 不过,有一个问题需要被注意:没有人会向TCP发送方通报中间设备中的“缓冲区”状态。

TCP发送方会自行“估计”中间设备中的缓冲区状态,并为自己维护一个变量,这个变量被称为拥塞窗口(cwnd)。 发送方永远不会发送超过其拥塞窗口大小的数据。 假设 cwnd 为 15 个数据包,那么发送方无法向网络中发送 16 个数据包。 这个“估算值”是TCP发送方所做出的,它涵盖了从TCP发送方到TCP接收方的整个传输路径。 这并非对TCP发送方与TCP接收方之间“每一个中间设备”上的缓冲区占用情况的估计。 因为发送方无法知道中间设备的数量。 此外,对于同一连接来说,数据包的传输路径也会发生变化。 不同的数据包可以选择不同的路径,从发送方到达接收方。

那么,这个“估计过程”在TCP发送端是如何开始的呢?cwnd的初始值是多少呢?答案是……慢启动算法。

慢启动算法:

目的:开始对 cwnd 进行“估算”的过程,尽快得出一个“合理的估计值”。

算法

  • 以初始值 cwnd 为起点(在 Linux 系统中,默认值为 10 个段;而在 1980 年代时,该数值为 1 个段)。
  • cwnd的初始值被存储在Linux内核中的一个名为“initcwnd”的变量中,该值是一个固定不变的数值。
  • 当算法开始运行时,cwnd的值被设置为initcwnd。
  • 另一种看待 cwnd 的方式是:“TCP 发送方在不等待确认消息的情况下,能够传输的最大段数。”
  • 在TCP协议中,还有一个非常重要的变量,它被称为“飞行中”或“管道”。
  • “Inflight/pipe”指的是那些已经被发送出去的数据包,但收件方尚未收到相应的ACK信号。也就是说,这些数据包仍然处于发送方和接收方之间的传输过程中。
  • 在飞行过程中,如果网络带宽足够的话,那么使用“inflight ≤ cwnd”这种表达方式更为合适。不过,如果网络带宽不足的话,那么使用“inflight = cwnd”这种表达方式则更为理想。

插图/图片

最初,cwnd和initcwnd的值均为10个段。发送方在等待单播确认到达之前,就先发送了10个段。
每当收到一个ACK信号时,发送方就会将cwnd的值增加1个段,同时向网络中发送2个新的段。

cwnd = 10 + 1 = 11,新的cwnd为11。不过现在只有9个段落在传输过程中。发送方可以在传输过程中发送价值等于cwnd值的段数。因此,发送方在传输过程中会再发送2个段位。

in-flight = in-flight - 1 + 2 // 减1是因为我们收到了确认信号;加上2是因为我们发送了2个新的数据包。
在飞行过程中 = 10 - 1 = 9 + 2 = 11

因此,如果所有数据段都能成功被确认,那么cwnd的值最终会在一个RTT时间内翻倍。所有10个ACK消息都将在1个RTT的时间内到达发送方,此时cwnd的值就会变为20。现在,有20个数据段正在传输中。

关键要点

Cwnd会持续增加,每次收到ACK信号时都会增加一定的数值。发送方在单次RTT之后不会将Cwnd翻倍,而是每次收到新的ACK信号时,Cwnd就会逐渐增加1。TCP发送方不会等待所有10个段的数据都收到后才会增加Cwnd。这种行为会导致网络带宽的浪费,因为直到所有ACK信号都被接收之前,都不会发送新的数据,从而无法充分利用网络带宽。

缓慢的启动/重启过程:

当 cwnd 达到其最大值 ssthresh 时,或者检测到数据包丢失时,慢启动机制就会终止,然后另一种算法会被激活,以继续处理后续的情况。

但是,当TCP连接处于空闲状态超过一定的时间段时(即等于RTO),发送方就会撤销其对cwnd的估计,因为该估计值已经无法再被更新了。在空闲时间结束后,如果发送方继续发送更多的数据段,那么它会重新启动慢启动算法,以重新估算出合适的拥塞窗口大小。

AIMD(加成性增长与减除性减少机制):

当发生数据包丢失时(即TCP发送方未能获得某个特定数据包的确认),或者当算法达到“慢启动阈值”时,慢启动就会终止,而AIMD则开始起作用。在TCP连接开始时,ssthresh的值为∞。当发生数据包丢失时,ssthresh会被更新为cwnd的一半。当检测到数据包丢失时,AIMD会将cwnd减少50%;而每次RTT结束后,cwnd会增加1(与慢启动不同,慢启动是每收到一次确认才增加cwnd)。

如果TCP连接被重置了,那又有什么问题呢?

TCP发送方需要获得一个“新的估计值”,这个估计值是基于多个RTT时间计算得出的。例如,假设当TCP连接因空闲状态而重新建立时,cwnd为1024个段。现在,TCP发送方将cwnd初始化为10个段,然后采用慢启动算法来逐步增加cwnd。这样,TCP发送方需要10个RTT时间(如果每个RTT时间为100毫秒的话,那么总共需要1000毫秒)才能将cwnd增加到1024个段。

Linux命令:

在 Linux 内核中,通过使用以下命令来操作 SSR:

检查 Linux 内核中 SSR 的默认设置

$ sysctl net.ipv4.tcp_slow_start_after_idle

预期输出(即,SSR功能已启用的情况):

$ net.ipv4.tcp_slow_start_after_idle = 1

禁用“慢启动重启”功能(对于服务器来说非常重要,但对于客户端来说则不太重要)。

$ sudo sysctl -w net.ipv4.tcp_slow_start_after_idle=0

预期输出:

$ net.ipv4.tcp_slow_start_after_idle = 0
              马上抢免费试听资格
意向课程:*必选
姓名:*必填
联系方式:*必填
QQ:
思博SPOTO在线咨询

相关资讯

即刻预约

免费试听-咨询课程-获取免费资料