本文主要讨论Congestion Control Protocols中的Dynamic Adjustment,而不是Pricing和Reservation。
Host-Based Dynamic Adjustment
每一个主机遵循算法如下:
- 选取一个初始速率R
- 尝试着以R为速率发送一段时间
- 有没有经历拥塞?
- 有,降低R
- 没有,增加R
- 重复这个过程
这个算法显然还有一些困难需要解决:
- 怎么选取初始速率?
- 怎么检查拥塞?
- 怎么增减?
下面来逐渐解决这三个问题。
Detecting Congestion
由两个方法构成
Loss-based (基于丢包的检测)
TCP使用
优点:
- 信号明确:数据包只有丢与被丢两种情况
- 天然兼容TCP: TCP本身就需要检测丢包,无需额外新增机制
缺点:
- 丢包 ≠ 拥塞:校验和错误,链路误码等也可以导致丢包
- 容易误判
- 反馈滞后,检测丢包的时候网络队列已经占满 (如果是由于网络队列丢包的,那么当检测到的时候网络队列已经占满),相当于出事了你才去补救,显然是不及时的。
(丢包:当发送方超时没有收到ACK,或者收到3次重复的ACK时判定为丢包)
Delay-based (基于延迟的检测)
TCP不使用
实现较为困难:
- 延迟波动复杂
- 长期难以精确实现
Discovering an Initial Rate
- 从较小值开始
- 快速递增 (不然会造成资源浪费)
如果线性增长,会浪费带宽、
所以我们要使用指数函数来增长
How can we Increase and Decrease? (速率调整)
- 快速调整 R -> 2R , R -> R / 2
- 慢速调整 R -> R + 1 , R -> R – 1
排列组合有四种组合策略:
- AIAD 加法增 加法减
- AIMD 加法增 乘法减 TCP标准算法(避免拥塞,实现带宽利用率与公平性的平衡)
- MIAD 乘法增 加法减
- MIMD 乘法增 乘法减
至于为什么AIMD实现了最好的速率调整,直观上很容易理解,课程给出了一张非常好的图如下,非常便于理解,但是具体证明在此不予赘述,可以自行搜索

Review: Setting Window Size
发送方会维护一个大小为W的窗口,用来控制同时再网络中传输但是没有确认的数据包个数。
怎么确定这个大小W呢?
- 不超载接收方 (流量控制)
接收方会通过接收窗口(RWND)告知发送方自己剩余的缓冲区空间,这里的接收窗口实际上是一个数值。发送方不能超过RWND允许的数据量。
- 不超载网络链路 (拥塞控制)
发送方通过拥塞窗口 (CWND) 控制发送量,当然他也是个数值。这个窗口由拥塞控制算法动态调整,避免网络发生拥塞。
W = min(RWND, CWND) 取二者的最小值,很多时候RWND > CWND, 这时候W由拥塞窗口决定
Event Driven Instead of RTT
最理想情况下,每个迭代持续一个RTT (往返时间),因为RTT是数据包从发送方到接收方再返回确认的时间,每经过一个RTT,发送方就能接收反馈。
但是RTT难以精确测量,并且会动态波动,因此不能直接使用。所以我们不使用RTT,而是事件驱动更新机制,有以下方式更新:
- 收到新数据的ACK -> 说明没有拥塞,CWND增大 (慢启动指数增长或拥塞避免时线性增长)
- 收到3个重复的ACK -> 说明大概率有单包丢失了,但不算特别严重 -> 执行乘性减将CWND降低,快速恢复。
- 超时计时器到期,判定丢包 -> 说明属于较为严重的网络拥塞 -> 因为太过严重,将CWND重新重置为初始值,重新从慢启动开始。
下面叙述一下Event-Driven Slow Start:
这里是慢启动阶段:
每次收到一个ACK,可以滑动窗口向前滑动 (已应答就不在窗口内了),发送一个新包,CWND加1,综合来看每收到一个ACK,总共可以发送2个新包,这等效于经过一个理想的RTT然后CWND直接翻倍的增长规律。
SSTHRESH (慢启动阈值)
SSTHRESH 一开始会被设置为一个较大值,TCP检测到丢包事件后,立即更新SSTHRESH:
SSTHRESH = 当前CWND / 2
这里的CWND指的时发包瞬间拥塞窗口的大小,然后除以2作为后续的安全带宽参考。
- CWND < SSTHRESH 慢启动阶段 (指数增长,符合上面的叙述,宏观上等价于过一个RTT然后CWND翻倍)
- CWND >= SSTHRESH 进入拥塞避免阶段 (线性增长,每收到一个ACK,CWND += 1 / CWND,宏观上等价于没经过一个RTT,CWND += 1)
以上的1均为报文数 (packet),如果用字节数 (byte) 表示CWND需要结合MSS,把1替换为MSS进行计算。(cwnd += MSS * MSS / cwnd)
评论(0)
暂无评论