首页/网络/协议速查/慢启动与初始拥塞窗口
TCP 与 UDP54 条

慢启动与初始拥塞窗口

连接刚建立时不知道网络容量,cwnd 从初始窗口(Linux/RFC 6928 为 10 MSS)出发每 RTT 翻倍,呈指数增长直到丢包或达到 ssthresh。

协议速查网络更新于 2026-10-13

慢启动是什么

TCP 刚建立连接时并不知道链路能承载多少数据,于是先按一个保守的初始拥塞窗口发一小批数据:每收到确认就把窗口翻倍,呈指数增长,直到出现丢包或达到 ssthresh 门槛,再转入拥塞避免阶段线性增长。现代实现(RFC 6928)把初始窗口提到 10 个 MSS 约 14.6KB,以缩短短连接的首屏耗时。

基本信息

初始拥塞窗口10 MSS,约 14.6KB(历史值曾为 3-4)
增长方式每收到一个 ACK 窗口加一,宏观看是每 RTT 翻倍
退出条件cwnd 达到 ssthresh 或检测到丢包
规范RFC 6928、RFC 5681 §3.1
相关参数net.ipv4.tcp_slow_start_after_idle 控制空闲后是否重新慢启动
观测工具ss -ti 输出中的 cwnd 字段

典型使用场景

  • 解释小文件页面的首字节与首屏延迟:短连接几乎全程处于慢启动
  • 评估连接池与 keep-alive 的价值:复用连接可以跳过重复的慢启动过程
  • 高延迟链路上诊断吞吐上不去:窗口增长需要足够多的 RTT 才能填满带宽
  • 排查长连接空闲后首包变慢:tcp_slow_start_after_idle 会让窗口重新回到起点
  • 估算文件传输的爬坡时间,为分片并发数提供依据

观察拥塞窗口增长

观察拥塞窗口增长
ss -ti '( dport = :443 )' | head -20    # 输出里的 cwnd:10 表示 10 个 MSS
ss -tin state established | grep -E 'cwnd|rtt'
sysctl net.ipv4.tcp_slow_start_after_idle   # 1 表示空闲后重新慢启动
sysctl net.ipv4.tcp_init_cwnd_reduction     # 丢包后如何收敛
nstat -az TcpExtTCPLostRetransmit | head -3

阶段与行为

阶段窗口变化触发条件
慢启动每 RTT 翻倍,指数增长连接刚建立或超时重传后
拥塞避免每 RTT 线性加一cwnd 达到 ssthresh 之后
快速重传/恢复窗口减半后再缓慢增长收到三个重复 ACK
空闲后重启动窗口回落重新增长tcp_slow_start_after_idle 生效且连接空闲较久
对页面加载这类大量短连接的场景,最重要的优化不是调窗口参数,而是复用连接:HTTP/2、连接池、keep-alive 都能让后续请求跳过慢启动,比调大初始窗口的收益更稳定。
tcp_slow_start_after_idle 默认为 1:长连接空闲一段时间后再发数据会重新从小窗口开始。交互型长连接(如数据库连接池)在延迟敏感场景可以考虑关闭,但要以链路质量可靠为前提。

易错点

  • 以为带宽够用就不会慢启动:只要连接是新建的,窗口就必须从初始值爬升,物理带宽再大也要等若干 RTT
  • 长连接空闲后突然变慢却查不出原因:漏看 tcp_slow_start_after_idle,窗口被重置回初始值
  • 把初始窗口调得过大:在网络质量差的路径上会造成更多丢包与重传,反而降低吞吐
  • 在丢包率高的国际链路上期望长肥管道跑满:受拥塞控制与窗口增长限制,单连接吞吐有物理上限

数据来源与参考

  • RFC 6928(初始窗口 10)
  • RFC 5681 §3.1

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌