说实话,网络问题排查是我日常工作中最讨厌的环节之一。上一秒还正常的服务,下一秒用户就反馈“页面打不开”,可你敲 ping 一切正常,看 CPU、内存也没毛病,最后折腾半天才发现问题出在链路质量上。这种时候,我第一个找出来的工具必然是 iperf——在 Linux 圈里,它就是最经典、最趁手的网络性能测试工具。无论你是运维、网络工程师还是后端开发,只要涉及“这条链路到底能跑多少带宽”这样的问题,iperf 都能用一两分钟给你一个靠谱的答案。
我不喜欢花几分钟 pcap 抓包,也不爱开着浏览器去 speedtest 网站上测(那测的是公网到节点机的速度,不是你要评估的链路)。iperf 的价值在于:它在两台机器之间建立真实的客户端/服务端连接,通过 TCP 或 UDP 协议拼命发包收包,直接把“链路实际吞吐量”“延迟抖动”“丢包率”这些硬指标量化出来。这篇博文我不打算念手册,而是把我这些年实际使用 iperf 的经验、踩过的坑,以及怎么围绕结果做定位,一次性写清楚。你可以把它当成一份能直接抄作业的实操笔记。
这篇内容适合谁?搞运维的、调网络的、刚入行想搞懂基础工具的小白,以及想评估专线、局域网、无线网络质量的人。看完你至少能完成从安装到分析结果的全流程,遇到“带宽不达标”也能自己一步步排查。
1. iperf 到底是什么,以及它能帮你搞清楚哪些事
1.1 什么时候我第一个想到 iperf
我一般把 iperf 当作网络链路的“压力测试机”。平时我们用 ping 只能确认目的地可达性和 ICMP 往返时延,但 TCP 层的吞吐表现、拥塞窗口如何变化、中间设备是否丢包,ping 完全给不了答案。像下面这些场景,单纯 ping 根本不够:
- 新上了两台服务器,网线、交换机、网卡都是新的,想验证一下 10G 链路是否真的达到万兆;
- 用户抱怨跨机房数据同步太慢,但两端机器 CPU 都很空闲,不知道怎么说服网络团队;
- 无线网络信号显示“满格”,可实际传输速率几乎腰斩,想证明是射频环境问题而不是终端问题;
- 专线刚开通,合同写明 100M 带宽,验收时对方又解释“瓶颈在你那边”,你需要一个工具甩出量化结论。
这些场景的本质都是一件事:需要在两个指定节点之间,制造持续、可控制的网络流量,然后读取链路层面的性能指标。这正是 iperf 的核心工作方式。它不像 speedtest 那样依赖公网节点,也不像 ping 那样只能简单测响应,它是在你指定的两台机器之间直接对话,因此测得的结果能真实反映这两点之间整条链路的表现。
用一句话概括:iperf 是衡量“两台主机之间网络链路能跑多快、丢多少包、抖动多大”的工具。它在 Linux 下是标准的网络性能测试工具之一,几乎每个发行版的仓库里都有,安装方便,使用门槛也不高。
1.2 它和常见网速测试工具的根本区别
很多人第一次接触 iperf 会问:为什么不用下载大文件的方式看速度?或者直接开个浏览器去测速网站,不是更直观吗?这里面的关键区别,在于“你控制了什么”。
测速网站:你只能选择最近的测速节点,流量路径不可控,上传和下载方向固定,中间跨越多个运营商骨干网,结果受到上一跳带宽、NAT、QoS 策略的影响非常大。测出来的数字只能说明“你到那个节点的体验”,不能说明“你服务器 A 到服务器 B 的链路”本身。
下载大文件:文件缓存在 CDN、磁盘 IO 瓶颈,或者收发两端不同的磁盘速度都会干扰结果。很多时候你以为是网络慢,其实是磁盘先撑不住了。iperf 默认不写磁盘,数据直接从内存收发(也可以指定-F参数传文件,我后面会讲到),它把磁盘 IO、Web 服务等上层干扰彻底剥离,专门压测网络协议栈。
iperf 与测速网站、文件下载测试的本质差异,就是“链路可控性”和“指标可读性”。它让你在两台指定主机之间产生流量,并且以 1 秒为粒度输出实时带宽、重传次数、抖动、丢包等信息,还能自定义协议(TCP/UDP)、并行流数、测试时长。这样我们就可以对同一链路做反复、可控的压测,对比不同参数的结果,把问题定位到具体方向。
打个比方:测速网站像用“称体重”来判断身体健康,iperf 则更像让运动员上跑步机做动态心肺测试。前者只给你一个笼统数字,后者能针对性地告诉你“极限心率是多少、每公里配速多少、哪里是短板”。
2. 原理先搞懂:客户端/服务端模型与各平台安装
2.1 iperf 的工作模型和 TCP/UDP 两套逻辑
iperf 的架构非常简单,就是一个客户端加一个服务端:一台机器运行服务端(server),等待客户端(client)连接;客户端指定服务端 IP 和端口后,开始持续发送数据。服务端在测试结束后会汇总结果,客户端那边同样会打印一份结果,两边的数据一般是一致的,但需要注意,有少数情况下单边数据会不准。我后面会讲为什么建议两边都看一眼。
它的测试逻辑分两种:
TCP 模式下,客户端默认会以“尽可能多”的方式发送数据,也就是让拥塞控制算法去接管发送速率,服务端只管接收和确认。TCP 的结果核心是吞吐量(Throughput)、传输速率(Mbps)以及重传(Retransmission)。iperf 甚至能直接统计出重传次数,这对于验证链路质量很好用。
UDP 模式下,客户端以固定速率发包(默认 1Mbps,可加-b指定任意带宽),服务端统计收到多少个包、少了多少个包、到达时间抖动。UDP 没有重传机制,因此结果直接反映链路的丢包率和抖动。这对评估实时音视频、组播、以及承载在 UDP/TCP 隧道上的业务很有参考价值。很多项目里用 UDP 测试来验证综合布线能不能扛住大流量广播,也是因为这个模式能直观体现“极限发送下的丢包”。
一个容易混淆的点:很多人以为 iperf 测试 UDP 时,设置-b 1G就是把链路打满测“最大带宽”。其实 UDP 模式测的是“在固定发送速率下,网络是否满负荷且不丢包”。如果你设 1G 跑到 5% 丢包,说明该链路承载不了这个速率;如果你逐级上调速率测试,找丢包率开始显著升高的临界点,那才是在评估“这条链路能承载多少 UDP 业务”。
2.2 安装 iperf 的几种常见姿势
iperf 在 Linux 发行版里基本都能直接装,我用过的几类系统命令如下:
- Debian/Ubuntu:
sudo apt update && sudo apt install -y iperf3 - RHEL/CentOS/Rocky/AlmaLinux:
sudo dnf install -y iperf3,老版本用 yum - openSUSE:
sudo zypper install iperf3 - Arch Linux:
sudo pacman -S iperf3 - macOS:
brew install iperf3 - Windows:去官方仓库或者 GitHub 上下载 exe,或者用 WSL 在 Linux 环境里跑
需要注意一个历史问题:现在仓库里默认安装的一般是 iperf3,但你可能会遇到既有 iperf2 又要装 iperf3 的情况。如果是老系统、老脚本,可能还在用 iperf2,命令参数与 iperf3 并不完全兼容,像双向同时测试(-d)还是 iperf2 才支持,iperf3 直到现在都不支持真正的同时双向。所以装之前先确认一下版本:iperf3 -v,服务端和客户端两端版本尽量保持一致,我是见过 iperf3 客户端连 iperf2 服务端,卡在协议协商阶段半天没动弹的。
如果服务器处在内网隔离环境,没有外部 Yum/Apt 源,还可以用静态编译的二进制。iperf3 官方仓库提供各平台预编译包,下载下来给上执行权限就能跑。但注意静态包可能依赖较少,部分高级功能(比如绑定 CPU)可能受限,不过基本测试完全够用。
3. 核心参数与经典用法:照着做就能出结果
3.1 我不会背参数手册,但心中常备这几个
iperf3 的参数非常多,实战里我真正高频使用的不超过 15 个。先把最常用的整理成表格:
| 参数 | 作用 | 常用场景 |
|---|---|---|
-s | 以服务端模式运行 | 被测试目标机 |
-c <IP> | 连接指定服务端 | 发起测试的机器 |
-p <port> | 指定端口,默认 5201 | 服务端端口被占用或要区分多组时 |
-t <seconds> | 测试时长,默认 10 秒 | 需要更长时间观察稳定性时设为 30/60 |
-i <seconds> | 结果打印间隔 | 默认 1 秒打印一行速率 |
-P <n> | 并行客户端连接数 | 提高总吞吐、压出多核能力 |
-u | 使用 UDP 模式 | 测抖动、丢包、承压线 |
-b <bandwidth> | UDP 发送带宽(TCP 也可限速) | UDP 指定期望速率,如-b 500M |
-R | 反向模式:服务端发、客户端收 | 专门测下载方向的性能 |
-w <size> | TCP 窗口大小 | 大带宽长距离时调整窗口 |
-M <mss> | 设置 TCP 最大段大小 | 测试 MTU 是否对吞吐有影响 |
-O <sec> | 忽略前 N 秒结果 | 排除慢启动与初始速率波动的影响 |
-J | 以 JSON 格式输出 | 脚本化采集结果做可视化 |
-F <filename> | 从指定文件发送数据 | 模拟包含文件传输的真实负载 |
-A <cpu> | 绑定 CPU 核心 | 高带宽测试时减轻调度抖动 |
这中间有个容易忽视的参数是-O。默认 10 秒测试里,TCP 连接刚开始有慢启动过程,前 1-2 秒速率可能远低于稳定值。比如你测一条 10G 链路,前 3 秒还在爬升,后 7 秒稳定,直接看平均值会被拉低很多。我一般加-O 3或-O 5,避开启动阶段再统计,结果更有说服力。
还有窗口大小-w。TCP 窗口决定了在往返时间(RTT)内能发送多少数据而不等确认,窗口太小,跨地域高延迟链路就跑不满。比如 10G 链路、RTT 为 50ms,理论上需要窗口至少 10Gbps × 0.05s = 500Mbit,也就是约 62.5MB,才能填满管道的带宽时延积。这个值很大,系统默认往往达不到。不过也别一上来就乱设,普通场景先用默认值,结果不行再调 RTT 相关的参数。
3.2 一条命令跑通 TCP 带宽测试
场景:两台 Linux 机器,IP 分别是 192.168.1.10(服务端)和 192.168.1.20(客户端),要测从客户端向服务端发送数据的最大带宽。
第一步,在服务端启动:
iperf3 -s默认监听 TCP 5201 端口,屏幕上会显示等待连接的提示。如果服务器上开了防火墙,记得放行:firewall-cmd --add-port=5201/tcp或ufw allow 5201/tcp,UDP 测试还要放行 UDP 端口。
第二步,在客户端发起测试:
iperf3 -c 192.168.1.10 -t 30 -i 1 -P 4含义是连接 192.168.1.10,跑 30 秒,每秒打印一次,同时开 4 个并行流。跑完客户端会打印总计结果。假设结果为 9.42 Gbps 左右,而两端网卡都是 10G,说明链路基本打满;如果只有 1.2 Gbps,那就值得往下排查了。
我补充一个细节:iperf3 的-P 4并不是开启 4 个线程,而是起了 4 个独立的客户端连接,所以服务端也能看到对应数量的连接。单条 TCP 流在多核高带宽下经常无法达到线速,原因是 TCP 处理通常绑定在某个 CPU 上,许多网络中断都挤到同核。所以万兆及以上测试,推荐用-P提高并行流数量,再观察是否会提升总带宽。
如果想测反方向(服务端发送、客户端接收),加-R即可:
iperf3 -c 192.168.1.10 -R这个参数比把两端角色对调更省事,等于告诉 iperf3“方向反转”。单测上行、单测下行加起来,就能完整评估一条链路的上行和下行了。
3.3 UDP 模式:带宽、抖动、丢包一个不少
UDP 模式乍一看命令和 TCP 差不多,只要加-u:
iperf3 -u -c 192.168.1.10 -b 100M -t 30 -i 1意思是以 100Mbps 的速率发送 UDP 数据,持续 30 秒。测试结束后,客户端和服务端都会显示接收带宽、抖动(Jitter)和丢包率。输出会类似:
[ 5] 0.00-30.00 sec 356 MBytes 100 Mbits/sec 0.001 ms 0/260642 (0%)这里的0/260642 (0%)表示 26 万多个包一个都没丢,抖动只有 0.001ms,非常干净。如果丢包率比较高比如 5%,那基本可以断定链路扛不住这个速率的 UDP 流量。
我在实际项目中常用 UDP 模式来定“临界带宽”:从 200M 开始测,每次递增 100M,记录各速率下的丢包率;当丢包率超过 0.1% 时,把上一个无丢包的速率作为这条链路稳定的业务承载上限。这个方法在评估无线回传、专线 QoS 时特别有效,因为 TCP 模式会自动降速重传,反而不容易暴露底层丢包问题。
需要注意的是,UDP 模式下输出的带宽统计,要区分“发送带宽”和“接收带宽”。如果出现大量丢包,接收端统计到的带宽会低于发送端,两边数字对不上,恰恰说明链路上丢包严重。我遇到过有同事只看客户端输出,看到 100M 的发送带宽就以为没有丢包,其实服务端那边已经丢了 20% 的包。所以 UDP 测试一定要两端对比。
4. 实战案例:我在真实网络环境里的测试记录
4.1 验证万兆链路是否真的达标
我之前帮客户验收一段约 50 米的数据中心万兆链路,设备从交换机、跳线到服务器网卡都是新的。按流程走,先确认链路协商状态:
ethtool eth0输出里Speed: 10000Mb/s说明网卡协商为万兆。接下来在服务端跑 iperf3 -s,客户端用:
iperf3 -c 10.10.10.10 -i 1 -t 30 -O 5 -P 8结果每秒打印的速率一路稳定在 9.8Gbps 左右,总计 9.86Gbps,损耗只有 1.4%,有交换机转发头、协议头开销,这个结果算是非常理想的了。这时候我可以放心地跟客户说链路没问题。
如果结果是 1Gbps 或 2Gbps 左右,最可能是网卡协商成了千兆或协商异常,马上用 ethtool 检查。还有一种情况是网线没到位、氧化或质量差,在万兆下表现为速率忽高忽低甚至频繁重传。测试时看到重传数字飙升的话,可以尝试换线验证;线缆问题在万兆网络中比在千兆中常见得多。
补充一个经验:万兆测试时 CPU 也要关注。用top或mpstat观察网卡中断所在核心的 CPU 占用,如果接近 100%,说明单核已经成为瓶颈。这时候把 iperf 客户端进程绑定到另一个核,或者用-P增加并行流分摊负载;还可以开启网卡多队列(ethtool -L eth0 combined 8)。这些优化做完通常总吞吐能明显提升。
4.2 无线网络和跨机房专线的典型测试方法
无线网络测试比有线复杂,因为除了带宽,信道干扰、信号强度、天线协商速率都会影响结果。我通常的做法是,在无线路由器同一侧的机器跑服务端,在终端侧(笔记本或手机端 Linux 发行包里)跑客户端,以 30 秒为周期分别测多次,每次换不同位置或时段。比如在一个办公楼里,同一个 AP 下,近距离测到 866Mbps(80MHz 频宽下的协商速率),隔了两堵墙调到 260Mbps,这个结果能很好辅助判断点位是否合理。但要注意,无线的速率波动很大,单次测量没有统计意义,我一般至少测 5 次取中间值,并且测试时关闭其他大流量应用。
跨机房专线的测试思路又不一样。专线链路通常有带宽上限(合同写 100M 或 200M),这时就不要用 TCP 默认模式去猛冲,因为两条机器中间的专线 QoS 可能已经限制了带宽,你用默认模式反而会测得与合同不符的结果。更好的方法是先用 UDP 模式验证“合同带宽下的丢包率”:
iperf3 -u -c 10.0.0.2 -b 90M -t 60 -i 5在一根 100M 的专线上,以 90Mbps 发包,如果丢包率持续为 0,抖动低于 1ms,那么链路质量不错。然后再用 TCP 模式看吞吐量和重传情况,设置为 60 秒、-O 10,看它实际稳定在多少。如果 TCP 只能跑到 40Mbps,但 UDP 以 90Mbps 发包却不丢,那大概率是两端主机协商出的 TCP 窗口太小或拥塞控制不合适,而不是专线本身的问题。这两步测试的思路完全不同,一个测链路物理容量,一个测 TCP 协议栈实际效果,组合起来才能定位瓶颈到底在哪一头。
5. 速度不达标时的排查思路与常见坑
5.1 结果异常时先按这个顺序排查
我发现很多人拿到不理想的 iperf 结果后,第一反应是反复调参数,其实大多数问题不是参数造成的。按下面顺序排查会高效很多:
第一,两端网卡协商速率是否一致。千兆网卡不会跑到万兆,这看着像废话,但真遇到过 10G 服务器插在千兆交换机上,两边都是绿色灯,看起来“正常”,一测就只有 900Mbps。用ethtool eth0 | grep Speed看一下。
第二,链路中间设备与线缆。接线是光纤还是铜缆,模块是否匹配;交换机端口是否被限速(端口限速策略)。跨运营商或跨机房时问网络供应商出口带宽策略。有人会问“我怎么知道中间是不是限速了”,UDP 模式测临界带宽就能侧面验证。
第三,TCP 拥塞控制与窗口。Linux 默认拥塞控制算法是 cubic,在高带宽长延迟链路上可能不够激进,可以临时改成 bbr 看是否改善(sysctl net.ipv4.tcp_congestion_control=bbr)。TCP 窗口可按之前说的带宽时延积计算来调。
第四,CPU 与中断。使用mpstat -P ALL 1观察某个核心是否被打满,尤其万兆网卡中断默认可能都在 CPU0。解决思路是开启网卡多队列、RSS、调整 irqbalance,或给 iperf 绑定 CPU。
第五,内存与 socket buffer。如果net.core.rmem_max和net.core.wmem_max过小,也会限制吞吐。大带宽测试时,可以把这些值调大,一般设置到 16MB 或 64MB 再试。
5.2 参数与配置层面的常见坑
- 服务端和客户端程序版本不一致。最常见的是服务端是 iperf2,客户端是 iperf3,连接建立后立即报错或不显示进度。检查版本,两端统一。
- 防火墙只放行了 TCP 5201,UDP 测试却提示 no route to host。UDP 测试需要放行对应 UDP 端口:
firewall-cmd --add-port=5201/udp。 - MTU 不一致导致分片重传。如果链路中某段 MTU 是 1500,你强行在两端设置 jumbo frame 9000,那么跨该段时可能出现分片,性能反而下降。测试时建议先统一 MTU,比如整条链路都是 9000,再测试。
- 测试时长太短。默认 10 秒对于高延迟链路不够稳定,我一般至少测 30 秒,去掉前 5 秒启动阶段。
- 只看单边结果。前面提到 UDP 必须两边对比,TCP 其实最好也两边对比,万一某一端程序异常、统计丢失,另一端的总吞吐可以佐证。
这个表是我整理的高频问题速查:
| 现象 | 可能原因 | 快速验证 |
|---|---|---|
| 吞吐量接近 900Mbps 但网卡是万兆 | 网卡协商为千兆或链路限速 | ethtool eth0 |
| 速率周期性抖动 | 链路拥塞或带宽限速生效 | 用 UDP 多个速率档逐步测试 |
| 重传次数非常高 | 线缆问题、交换机拥塞、MTU 不一致 | 换线/统一 MTU 后重测 |
| 单流测不满带宽 | 单核 CPU 瓶颈或 TCP 窗口限制 | 用-P多流、mpstat观察核心 |
| 服务端连接后无输出 | 端口冲突、版本不匹配 | 换端口、检查版本 |
| 客户端提示 no route to host | 防火墙未放行 | 放行 UDP/TCP 5201 |
5.3 把 iperf 变成你日常检查的一部分
有时候链路质量是慢慢劣化的,不是一下测不出速度。我自己会在监控脚本里定期调用 iperf3,把结果转成 JSON 落地成日志:
iperf3 -c 10.0.0.2 -t 10 -J >> /var/log/netperf.log然后用一个简单脚本从 JSON 里提取sum_received.bits_per_second、sum_received.lost_packets等字段,超过阈值就报警。这样时间长了还能看出链路性能和高峰期上下班之间的关系。对 TCP 测试还可以关注retransmits字段,如果持续增长,就能提前预警链路劣化。
还有一个我比较喜欢的小技巧:在服务端用iperf3 -s -D让它在后台跑,日志写到文件里,方便事后复盘。需要测试时再临时起服务端进程,也是完全可以的,但我倾向于正式环境用 systemd 托管一个 iperf3 service,避免端口被占用或者进程意外退出。
关于自动化还有一个值得提的扩展:因为 iperf3 官方命令不支持真正的同时双向测试,但业务场景中很多应用是同时上传和下载的。遇到这种情况,我通常会同时启动两个独立 iperf3 进程,一个测上行一个测下行,然后用 tcpdump 或者网卡流量统计对比。假如两个方向叠加后吞吐低于预期,至少能知道双向同时传输时的真实表现,不至于被单向数据误导。
我个人这几年的体会是,iperf 这个工具真正厉害的地方,不是能打出多漂亮的带宽数字,而是它能逼你去理解整条链路。测出 9Gbps 你得知道 CPU 有没有打满、窗口有没有调对;测出 500Mbps 你更得去查交换机、查网线、查协商状态。用得越久越觉得,它不是“一条命令”,而是你在网络问题里快速缩小范围的最好抓手。
最后分享一个小技巧吧:无论测试结果如何,记得把两端的 iperf 输出都保存下来。一个附带完整时间、两端 IP 和参数的结果文件,在跟网络供应商、硬件厂商沟通时非常有说服力。别问我为什么知道,吃过亏的人不只我一个。