4. Wireshark 抓包分析吞吐测试:在 iPerf 测试中同步抓包、分析 TCP 窗口与重传、定位吞吐瓶颈

吞吐测试跑完了,数字看着挺漂亮。但你真的信吗?

我见过太多案例——iPerf 报告显示 900Mbps,实际业务跑起来只有 300M。问题出在哪?就在 TCP 的细节里。今天咱们就用 Wireshark 把 iPerf 的流量扒开看看。

4.1 为什么要在 iPerf 测试中同步抓包?

iPerf 本身只告诉你「发了多少数据」。它不告诉你:

  • 数据包是不是在排队?
  • 窗口是不是被卡住了?
  • 有没有悄悄重传?

说白了,iPerf 是结果,Wireshark 是过程。我习惯在测试时两端同时抓包,这样能看清每一毫秒发生了什么。

核心原则: 抓包不是等出问题了再抓,而是测试一开始就同步启动。事后分析时,你才能把时间轴对齐。

4.2 抓包前的准备工作

别急着点开始。先做好三件事:

  1. 确认抓包位置——最好在客户端和服务端同时抓。如果条件有限,至少抓客户端侧。
  2. 设置过滤条件——只抓 iPerf 的端口,避免流量太大把 Wireshark 搞崩。
  3. 记录测试参数——iPerf 的窗口大小、线程数、测试时长,这些后面分析时都要用。

我曾经有一次忘了设过滤,抓了 5 分钟,文件 2GB 多。打开 Wireshark 直接卡死。嗯,从那以后我再也不敢偷懒了。

4.3 同步抓包的操作步骤

这里给出一套我常用的操作流程:

步骤 操作 说明
1 启动服务端 iPerf iperf3 -s -p 5201
2 启动客户端 Wireshark 过滤条件:tcp.port == 5201
3 启动客户端 iPerf iperf3 -c 192.168.1.10 -t 30 -w 256K
4 测试结束后停止抓包 保存为 pcapng 文件
5 服务端也抓一份 用于对比分析
小技巧: 在 Wireshark 里用 tcp.analysis.flags 过滤,能快速定位所有异常包——重传、重复 ACK、窗口零通告,一目了然。

4.4 分析 TCP 窗口:你的接收端在喊停吗?

TCP 窗口大小,决定了发送端一次能扔多少数据出去。如果窗口太小,发送端就得等 ACK,吞吐自然上不去。

在 Wireshark 里,找到 TCP Window Size 字段。我一般关注两个值:

  • 初始窗口——握手时协商的窗口大小
  • 实时窗口——每个包里的窗口值,动态变化

如果实时窗口一路下跌,甚至变成 0,说明接收端处理不过来了。这就是典型的「接收端瓶颈」。

注意: Wireshark 默认显示的是「原始窗口值」。要看到真实的可用窗口,得开启 Calculated Window Size 列。右键列头 → Column Preferences → 添加 tcp.window_size。

举个例子。有一次我帮客户排查,iPerf 报告只有 200Mbps。打开抓包一看,窗口从 64KB 一路掉到 8KB,最后变成 0。接收端是台老服务器,网卡中断处理不过来。换了个多队列网卡,问题解决。

4.5 分析重传:网络真的可靠吗?

重传是吞吐的隐形杀手。一个重传包,不仅浪费带宽,还会触发拥塞控制,把发送窗口砍半。

在 Wireshark 里,重传包会标成黑色(默认配色)。你可以用 tcp.analysis.retransmission 过滤出来。

我一般看三个指标:

指标 正常范围 异常信号
重传率 < 0.1% > 1% 说明链路有问题
快速重传 偶尔出现 频繁出现说明丢包严重
超时重传 几乎为零 出现即代表 RTO 触发

快速重传和超时重传的区别在哪?快速重传是收到 3 个重复 ACK 后触发的,超时重传是等不到 ACK 超时了。后者更严重,因为发送端会停下来等。

我曾经遇到一个案例,重传率高达 5%。抓包一看,全是超时重传。最后发现是中间交换机的一个端口有 CRC 错误,导致包被静默丢弃。换了根网线,重传归零。

4.6 定位吞吐瓶颈:三步法

有了抓包数据,怎么快速找到瓶颈?我总结了三步:

  1. 看吞吐曲线——Wireshark 的 IO Graph 能画出每秒吞吐量。如果曲线波动大,说明不稳定。
  2. 看窗口变化——用 tcp.window_size 画时间序列图。窗口持续下降,就是接收端瓶颈。
  3. 看重传分布——重传集中在某个时间段,说明那段时间链路有问题。

这三步走完,90% 的瓶颈都能定位。剩下的 10%,需要结合两端抓包做延迟分析。

关键思路: 吞吐 = 窗口大小 / RTT。窗口上不去,查接收端;RTT 太大,查网络路径;重传太多,查链路质量。

4.7 实战案例:一个典型的吞吐瓶颈分析

说个真实的案例。某次测试,iPerf 报告吞吐 500Mbps,但业务方说实际只有 200Mbps。我抓了包,发现:

  • 窗口大小始终在 64KB 左右,没变过
  • RTT 稳定在 2ms
  • 重传率 0.02%,正常

理论吞吐应该是 64KB / 2ms = 32MB/s ≈ 256Mbps。但 iPerf 报告 500Mbps,矛盾了。

仔细一看,iPerf 用了多线程(-P 4),每个线程独立窗口。4 个 64KB 窗口加起来就是 256KB,理论吞吐 1Gbps。但实际只有 500Mbps,说明瓶颈在别处。

再查 CPU 占用率——客户端 100%。原来是单核 CPU 撑不住了。换了个多核机器,吞吐直接飙到 900Mbps。

经验之谈: 别只看 iPerf 的数字。结合抓包看窗口、看 CPU、看中断,才能找到真正的瓶颈。

4.8 本章核心逻辑图

下面这张图总结了本章的分析流程:

吞吐测试抓包分析流程 吞吐测试抓包分析流程 ① 同步抓包(两端同时) ② 分析 TCP 窗口大小 ③ 分析重传与丢包 ④ 定位吞吐瓶颈 ⑤ 输出优化建议 抓包位置 客户端 + 服务端 过滤端口 窗口持续下降? → 接收端瓶颈 → 检查 CPU/网卡 重传率 > 1%? → 链路丢包 → 检查交换机/线缆

4.9 避坑指南

最后,分享几个我踩过的坑:

  • 别只抓一端——只抓客户端,你看不到服务端的窗口通告。两端对比才能定位问题。
  • 别忽略时间戳——Wireshark 默认用相对时间。建议改成绝对时间(View → Time Display Format → Date and Time),方便和 iPerf 日志对齐。
  • 别被「窗口缩放」骗了——TCP 握手时协商了 Window Scale 因子。Wireshark 会自动计算,但你要确认 Scale 值是否合理。Scale=7 意味着实际窗口是显示值的 128 倍。

我曾经犯过一个低级错误:抓包看到窗口是 64KB,以为没问题。后来才发现 Scale 因子是 0,实际窗口就是 64KB。而服务端支持 Scale=7,但客户端没开启。结果就是窗口被限制在 64KB,吞吐上不去。

嗯,细节决定成败。抓包分析就是这样——你越仔细,看到的就越多。