前言
在解释 TCP 的拥塞控制算法之前,需要了解 TCP 的两个窗口 RWND 接收窗口和 CWND 拥塞窗口。
接收端会维护接收窗口,会告诉发送端自己能够处理多少的数据,在发送 ACK 的时候,会告诉发送端自己的接收窗口的大小。
发送端会维护拥塞窗口,当网络上出现丢包等表明网络拥塞的情况时的情况时,需要修改自己的窗口大小来进行调整。
接收窗口的数值接收端能够明确的告诉发送端具体的大小,但是拥塞窗口没有明确的数值告诉发送方应该设置为多大。
为了解决这一问题,需要使用到拥塞控制算法,来告诉发送方应该设置窗口为多大来避免出现网络拥塞。
Tahoe 和 RENO 算法
在最原始的拥塞控制算法 Tahoe 中,将整个拥塞控制算法分为慢启动和拥塞避免两个部分。
慢启动指的是 TCP 连接刚建立的时候,一点一点的提速,试探网络的承受能力。每过一个 RTT,拥塞窗口的大小翻倍,直到 CWND 大小达到了设置的慢启动阈值 ssthresh 或者发生了丢包,进入到拥塞避免算法。
在拥塞避免的过程中,每过一个 RTT,CWND 的大小加一。当网络中发生丢包时,将 ssthresh 设置为当前 CWND 的一半,CWND 重置为 1 进入慢启动过程。
RENO 算法在 Tahoe 上进行了改进,当网络中出现了重复确认的情况时,Reno 算法只会降低 CWND 为当前 CWND 大小的一半,来提高网络的利用率。
Reno 的问题主要有以下几点:
- 在于受链路 Buffer 的影响很大。
- 因为其 CWND 大小每次只能加一,对于高带宽网络可能需要很长的时间才能够到达合适的拥塞窗口大小,在过程中会浪费大量的网络带宽,对于高带宽的网络利用率相当低。
- 每收到一个 ACK 就将 CWND 加一,对于 RTT 小的连接,其 CWND 的增长速度会很快,但是对于 RTT 大的连接,其在链路上占用的资源会比较小。RTT 小的连接会不公平的占用更多的带宽。
BIC 和 CUBIC 算法
BIC 算法在 RENO 的基础上做了一些改进,将拥塞避免的过程分为三部分
- 在丢包后将 CWND 降为丢包时 CWND 的常数倍(一般为 0.8), 并选择上次丢包时的 CWND 和本次丢包的 CWND 作为饱和点,然后以一个较快的速度增长 CWND 大小。
- 在接近饱和点,使用二分算法来去逐步的接近饱和点。
- 到达饱和点之后转为二次函数去探测下一个极限。当出现丢包时重复第一部分。
BIC 的好处在于丢包后能够迅速的进行恢复,在稳定期能够保持更长的时间,同时能够继续探测更高的带宽值。
CUBIC 比 BIC 算法在搜索拥塞窗口最大值的过程中更加的温和,使用三次函数来代替二分算法并且使用拐点值作为拥塞窗口的大小。
CUBIC 的优势在于因为其算法与 RTT 无关,所以更加公平,同时适合于网络带宽大的网络。
但是 CUBIC 依旧有缺点,其缺点在于当网络的传输带宽出现变化时,需要比较长的时间才能达到 Wmax,同时 CUBIC 更容易加重链路的负担。
VEGAS 算法
基于丢包的算法可以达到最大的传输速率,但是它是以高延迟和高丢包率作为代价的,但是它是以高延迟和高丢包率作为代价的。随着内存价格降低,交换机的 Buffer 越来越大后,容易导致 Bufferfloat,
与之前基于丢包的算法不同,VEGAS 算法会监控 RTT,在尝试增加发送速率时如果发现丢包或者 RTT 增加就降低发送速率,认为网络中出现拥塞,就将降低发送速率。
但是其致命的缺点在于不能很好的跟基于丢包的算法共存,在同时使用时会导致竞争不过基于丢包的算法,因此没有得到大规模的应用。
PRR 算法
TODO
BBR 算法
TODO