滑动窗口是什么
TCP 的接收方通过报文头里的窗口字段告诉发送方「我还能接收多少字节」,这就是端到端的流量控制。窗口降到 0 时发送方必须停发,并定期发送探测包等待窗口重新打开。真正决定发送速率的是接收窗口与拥塞窗口中的较小者:前者取决于接收方的缓冲与读取速度,后者取决于网络状况。
基本信息
| 窗口字段 | 16 位,最大 65535 字节 |
|---|---|
| 窗口缩放 | 通过选项把窗口上限放大,RFC 7323 定义,握手时协商 |
| rwnd | 接收窗口,由接收方缓冲与读取速度决定 |
| cwnd | 拥塞窗口,由拥塞控制算法决定 |
| 实际发送上限 | 取 rwnd 与 cwnd 的较小者 |
| 观测工具 | ss -ti 输出的 rwnd、cwnd 字段 |
典型使用场景
- 排查吞吐上不去:确认瓶颈在接收方窗口还是网络拥塞窗口
- 大带宽高延迟链路调优:窗口不足会直接限制单连接吞吐
- 定位应用读取慢:接收缓冲满导致零窗口,发送方被迫等待
- 分析抓包中的窗口变化,判断是应用层阻塞还是网络拥塞
- 评估缓冲膨胀带来的延迟增加,权衡窗口大小
查看窗口与缓冲设置
查看窗口与缓冲设置
ss -ti | head -30 # 输出中的 rwnd、cwnd、rtt
ss -tin state established | grep -E 'rwnd|cwnd'
sysctl net.ipv4.tcp_rmem # 接收缓冲的最小/默认/最大
sysctl net.ipv4.tcp_wmem # 发送缓冲的最小/默认/最大
sysctl net.ipv4.tcp_window_scaling # 窗口缩放是否启用
# 抓包观察窗口与零窗口
tcpdump -nn -v 'tcp port 8080' -c 20 | grep -i win指标读法
| 指标 | 含义 | 异常表现 |
|---|---|---|
| rwnd | 接收窗口,反映对方能收多少 | 降到 0 说明接收缓冲已满 |
| cwnd | 拥塞窗口,反映网络允许多少 | 频繁回退说明持续丢包 |
| 窗口缩放因子 | 把 16 位窗口放大到更大范围 | 未协商时高延迟链路吞吐受限 |
| 零窗口 | 接收方完全不接受新数据 | 发送方停发并周期性探测 |
| bufferbloat | 缓冲过大造成排队延迟上升 | 吞吐正常但延迟明显变高 |
接收方的应用读得慢,会直接压制发送方的速率:这不是网络问题,而是应用处理能力问题。看到零窗口时,先在接收端排查应用是否卡在慢查询、锁等待或 GC 停顿上。
窗口与缓冲不是越大越好:把接收缓冲调到很大,在链路拥塞时会造成缓冲区堆积,延迟显著升高(缓冲膨胀),交互型业务的体验反而下降。