排查tcp窗口耗尽需抓包观察win 0、重复ack无新数据、长时无ack且重传窗口极小;用-s0/-nn/-tttt确保字段完整;wireshark中查看窗口曲线、筛选tcp.window_size==0及窗口更新事件缺失;诱因包括应用读取慢、内核缓冲区小、中间设备压窄窗口或丢包。

排查TCP窗口耗尽导致的卡顿,核心是观察接收方通告窗口(Window Size)是否持续为0或极小,以及发送方是否因此停止发包。tcpdump本身不直接计算窗口利用率,但能完整捕获每个TCP段的窗口字段、ACK序列号和数据长度,足够你手动或脚本化识别窗口阻塞行为。
确认抓包时包含完整TCP头部和时间戳
窗口信息在TCP首部中,必须确保抓包不截断、不省略关键字段:
- -s0:强制抓取完整数据包(避免默认96字节截断导致看不到TCP窗口值)
- -nn:禁用DNS和端口解析,保证输出稳定可读
- -tttt:显示完整日期时间(精确到微秒),便于分析窗口停滞时长
-
指定网卡和过滤目标流:例如
tcpdump -i eth0 -nn -tttt -s0 'host 10.1.2.3 and port 8080'
识别窗口耗尽的关键特征
在tcpdump输出中逐行检查以下三点,任一成立即高度提示窗口问题:
- 看到
win 0字样:表示接收方通告窗口为0,明确拒绝新数据 - 连续多个ACK包只重复确认同一seq(如
ack 123456不变),且无新数据携带(length 0),但发送方此前已发过大量数据——说明接收方应用未消费缓冲区,窗口卡死 - 发送方发出的数据包后,长时间(>200ms)无对应ACK返回,且后续重传包的window字段仍为0或极小(如
win 1460但远小于MSS)
结合Wireshark做深度验证(推荐离线分析)
tcpdump抓包后保存为pcap文件,用Wireshark打开可直观验证:
- 右键任意TCP流 → Follow → TCP Stream,查看窗口大小随时间变化曲线
- 启用列显示 Window size scaling 和 Calculated window size,看是否长期趋近于0
- 筛选
tcp.window_size == 0,定位所有零窗口报文;再用tcp.analysis.window_update查看窗口更新事件是否缺失
常见诱因与快速验证方向
窗口耗尽不是孤立现象,通常由下游环节引起:
- 接收端应用读取慢或阻塞:检查对应进程CPU/内存是否异常,是否有阻塞式read()调用
-
接收端内核接收缓冲区过小:执行
ss -i查看rcv_space和rcv_ssthresh是否长期偏低 - 中间设备(如负载均衡器、防火墙)修改了窗口值:对比客户端直连服务端与经LB访问的tcpdump结果,看窗口是否被LB主动压窄
-
网络丢包引发窗口误判:若同时存在大量重传(
tcp.flags.retransmission),需先解决丢包,再看窗口是否恢复











