协议层面的延迟:TCP的拥塞控制与慢启动

跨云数据复制,说白了就是数据在广域网上跑。而广域网,几乎都跑在TCP之上。TCP是个好东西,可靠、有序、流量控制,样样都行。但它的这些特性,在跨云场景下,恰恰成了延迟的“帮凶”。

我个人习惯把TCP的延迟问题拆成三块来看:建连开销、慢启动的吞吐爬坡、以及窗口大小对延迟的放大效应。咱们一个一个聊。

TCP三次握手:还没发数据,先耗一个RTT

你想想看,客户端想跟服务端传数据,得先握个手。这个握手过程,至少消耗一个往返时间(RTT)。对于跨云场景,RTT动辄几十毫秒甚至上百毫秒,这个开销就很可观了。

具体流程是这样的:

  1. 客户端发SYN(同步序列编号)
  2. 服务端回SYN+ACK(同步确认)
  3. 客户端再回ACK(确认)

三次握手完成后,才能开始传数据。也就是说,在第一个数据包发出之前,你已经等了一个RTT。

关键点:对于短连接场景(比如频繁的API调用),三次握手带来的延迟占比极高。我建议在跨云复制中尽量使用长连接或连接池,避免每次传输都重新建连。

我的经验:我曾经优化过一个跨中美两地的数据同步任务。原始方案每次同步都新建TCP连接,光握手就耗掉200多毫秒。改成连接池复用后,整体延迟下降了近40%。

慢启动算法:吞吐量的“爬坡”过程

TCP建连之后,并不会立刻把带宽跑满。它会从一个小窗口开始,慢慢试探网络的承载能力。这个过程,就是慢启动。

慢启动的核心逻辑:

  • 初始拥塞窗口(cwnd)通常为10个MSS(最大报文段长度)
  • 每收到一个ACK,cwnd翻倍(指数增长)
  • 直到遇到丢包或达到慢启动阈值(ssthresh)

问题在于,跨云链路的带宽延迟积(BDP)通常很大。比如一个100Mbps的链路,RTT是100ms,BDP大约是1.25MB。而慢启动从10个MSS(约14KB)开始爬,要爬很多个RTT才能填满这个管道。

RTT次数 拥塞窗口(MSS) 吞吐量(Mbps)
0 10 1.2
1 20 2.4
2 40 4.8
3 80 9.6
4 160 19.2
5 320 38.4
6 640 76.8
7 1280 153.6

看到没?要跑满100Mbps的链路,需要6个RTT。如果RTT是100ms,那就是600ms的“爬坡时间”。对于短时间的数据传输,这个开销占比极高。

注意:慢启动不是“慢”,而是“谨慎”。它是在保护网络不被突发流量冲垮。但在跨云场景下,这个谨慎的代价就是延迟。

窗口大小与延迟的关系

TCP的窗口大小,决定了发送端在收到ACK之前能发多少数据。窗口越大,链路利用率越高,但延迟也越高——因为数据在缓冲区里排队。

这里有个关键公式:

吞吐量 = 窗口大小 / RTT

也就是说,要提升吞吐量,要么增大窗口,要么减小RTT。RTT是物理距离决定的,很难改。所以只能增大窗口。

但窗口不是无限大的。接收窗口(rwnd)受接收端缓冲区限制,拥塞窗口(cwnd)受网络状况限制。两者取最小值,才是实际可用窗口。

我遇到过一种情况:接收端缓冲区配得太小,导致窗口始终打不开。明明链路带宽很足,但吞吐量就是上不去。后来把接收窗口从64KB调到1MB,问题立刻解决了。

核心结论:窗口大小与延迟是“跷跷板”关系。窗口越大,延迟越高(因为排队),但吞吐量也越高。跨云复制需要在吞吐量和延迟之间做权衡。

BBR:新型拥塞控制算法

传统TCP的拥塞控制(比如CUBIC)依赖丢包来探测带宽。但跨云链路上,丢包不一定是拥塞导致的,可能是链路本身的质量问题。这就导致传统算法会过度降速,白白浪费带宽。

BBR(Bottleneck Bandwidth and Round-trip propagation time)是Google提出的一种新算法。它不依赖丢包,而是通过测量带宽和RTT来建模网络状态。

BBR的核心思路:

  • 测量瓶颈带宽(BtlBw)
  • 测量最小RTT(RTprop)
  • 根据这两个值计算最优发送速率

BBR的优势很明显:

  • 不依赖丢包,不会因为偶然丢包而大幅降速
  • 能更充分地利用高带宽长链路
  • 延迟更低,因为不会把缓冲区填满

我曾在AWS和阿里云之间的数据传输中测试过BBR。同样的链路,CUBIC的吞吐量只有40Mbps左右,换成BBR后直接跑到95Mbps。延迟也从120ms降到了80ms。

我的建议:如果你的跨云链路RTT超过50ms,或者带宽超过100Mbps,强烈建议试试BBR。Linux内核4.9以上版本已经内置支持,开启方式很简单:

# 查看当前拥塞控制算法
sysctl net.ipv4.tcp_congestion_control

# 切换到BBR
echo "bbr" > /proc/sys/net/ipv4/tcp_congestion_control

本章知识体系

下面这张图,把TCP协议层面的延迟问题串起来了:

TCP协议延迟问题知识体系 TCP协议延迟问题知识体系 TCP协议延迟 三次握手开销 慢启动算法 窗口大小与延迟 三次握手 SYN → SYN+ACK → ACK 至少消耗1个RTT 慢启动 cwnd指数增长 高BDP链路爬坡慢 窗口大小 吞吐量 = 窗口 / RTT 窗口越大,延迟越高 解决方案:BBR拥塞控制算法

这张图把TCP延迟的三个核心问题串在了一起。三次握手是建连阶段的固定开销,慢启动是传输初期的吞吐爬坡,窗口大小则决定了稳态下的延迟与吞吐量关系。而BBR,正是针对这些问题给出的一个系统性解决方案。

嗯,协议层面的延迟,说白了就是TCP的“好心办坏事”。它太想可靠了,太想公平了,结果在跨云这种高延迟、高带宽的场景下,反而成了瓶颈。下一层,咱们聊聊网络层面的延迟——路由、丢包、抖动,那又是另一番风景。