iperf3带宽测试全攻略:从单线程瓶颈到复杂网络实战

发布时间:2026/10/6 3:32:36
iperf3带宽测试全攻略:从单线程瓶颈到复杂网络实战 干这行久了会碰到很多测带宽测不明白的现场。客户说买了100M专线表上写的是100M两台服务器在同一台交换机上iperf3跑出来只有20M。然后一群人开始怀疑交换机、怀疑防火墙、怀疑线缆最后发现是iperf3的用法太基础——单线程、默认窗口、没有并行流任何一个环节都能把你压死在低速率上。iperf3这个工具几乎所有网工和运维手里都有但真正把它用好的人不多。百度上搜iperf3带宽测试翻来覆去就是一段iperf3 -s加一段iperf3 -c 192.168.1.1拿来测同一个二层网络勉强够用一放到跨防火墙、跨地域、多链路负载均衡、容器网络这些场景里立刻露馅。这篇我按自己平时在项目里用的套路把复杂网络的带宽测试从头到尾讲清楚包括多线程怎么开、UDP打流怎么打、窗口大小怎么算、结果怎么解读、踩过的坑怎么避。适合谁看你只要有网络基础平时要负责任何链路性能验证、故障排查、设备选型对比这篇能让你少走很多弯路。1. 为什么基础iperf3测不准三个隐藏瓶颈第一篇教程不会告诉你先别急着甩参数先理解一件事iperf3默认的测法根本测的不是链路带宽而是一条TCP连接在一台机器上一个CPU核上能跑多快。复杂网络里的瓶颈往往不在线缆而在软件栈和设备策略。把下面三个机制想透了你才知道该用什么参数去突破。1.1 单线程有天花板一个CPU核的吞吐上限没那么高iperf3默认只建立一条TCP流。一条TCP流从发送端到接收端要经过系统调用、协议栈的校验和计算、网卡驱动、中断处理这些处理全部落在同一个CPU核上。现代服务器虽然网卡有多队列但单条TCP连接在绝大多数系统上只会被哈希到固定的一个队列绑定到一个CPU核。这里先说个实测现象在2.5Gbps的链路上用默认单线程iperf3通常只能跑出1.2到1.8Gbps在10Gbps链路上单线程能跑上个3到4Gbps就已经算不错了。CPU单核性能、网卡驱动效率、DPDK还是内核协议栈都会直接影响这个天花板。所以当你看到带宽不达标第一反不应该是链路坏了而是你只开了一条流根本没有把链路跑满。解决办法就是用并行流也就是-P参数。一条流压一个核四条流就压四个核。我一般在测千兆以上链路时起步就是-P 4万兆链路直接-P 8甚至-P 16。跑之前先看一眼CPU负载如果某个核已经打满了那就说明你压到的是CPU瓶颈而不是链路瓶颈。这个后面结果分析部分再展开。1.2 默认窗口太小跨地域高时延链路必死第二个隐藏瓶颈是TCP窗口。TCP的发送速度受限于一个公式吞吐率约等于窗口大小除以RTT往返时延。也就是常说的带宽延迟积BDP。拿实际场景算一笔账假设链路带宽是1Gbps客户端到服务器RTT是20毫秒那BDP就是1Gbps × 0.02秒 20Mb ≈ 2.5MB也就是说这条TCP连接的理论发送窗口至少要达到2.5MB才能填满链路。但Linux默认的socket缓冲区可能只有几百KB窗口扩不起来吞吐自然上不去。操作系统里tcp_wmem/tcp_rmem的默认值通常比较保守偏保守的默认值往往不够用。这种情况下你用不着改系统全局参数那会影响所有业务流量风险大iperf3直接提供了-w参数专门设置TCP窗口大小。像我测跨地域的链路通常直接-w 4M或-w 8MWindows和Linux都认这个参数。注意窗口大小不是越大越好。超过BDP很多并不会继续提速反而浪费内存。稳妥做法是先 ping 测出RTT再按带宽 × 1.5倍RTT估算窗口然后向上取整设成 4M、8M 这种整数。比如上面那个例子2.5MB的BDP设 4M 就够了。还有一个容易忽略的点如果链路经过的中间设备防火墙、IPS在TCP三次握手里启用了TCP选项裁剪把窗口缩放因子Window Scale去掉了那即使你设置了大窗口也没用。这个可以通过在两台测试机上抓三次握手包看SYN报文的Window Scale选项来判断。1.3 网络设备按五元组哈希单流的瓶颈卡在设备单核上第三个坑在中间设备上。现在的防火墙、负载均衡、路由器很多都基于多核CPU做转发报文按五元组哈希分配到不同核心。如果你只建立一条TCP流所有报文都会被哈希到同一个核心那不管链路多大都会被设备的单核处理能力卡住。我曾经在一台低端防火墙后面测200M带宽单流怎么跑都在70M左右CPU也显示单核打满。后来加-P 4开了四条并行流四条流被哈希到四个不同核心总吞吐直接拉到180M。这几乎是复杂网络里最典型的测速提不上去的原因。所以在涉及防火墙、负载均衡等中间设备的场景里多线程不是可选项是必选项。从另一个角度讲这其实也是一个很好的测试手段单流速率差、多流总速率好说明设备按流哈希转发能力有限但总处理能力够用如果多流也提不上去那就要怀疑设备整体性能或链路本身了。2. 核心参数详解与选型逻辑像样带宽测试的标准姿势这一部分把我在生产环境里真正会用的参数一个个讲透。不要只看命令能跑通你要知道每个参数解决什么问题、在什么场景下该用不该用。2.1 并行流与合理流数-P 怎么开才不算乱开并行流数量没有标准答案取决于链路带宽、CPU核数、中间设备处理能力。我的起步经验值是千兆以内-P 2到-P 4万兆-P 8到-P 16。但有一个原则让发送端和接收端的CPU留有裕量不要让所有核心全部打满。如果CPU已经接近100%就算继续加流总吞吐也不会涨上去反而会增加上下文切换开销。还要区分并行流和并发进程。iperf3的-P 4是在同一个iperf3进程里创建4条独立连接如果你需要模拟多个客户端从不同源IP发起测试可以再指定-B绑定不同源地址或者开多个终端。比如测负载均衡设备的多IP会话分发就得用多个源IP、多条会话去打单一客户端IP配合多条流哈希粒度可能不够。2.2 窗口、缓冲区与零拷贝-w 和 -Z 的实际意义-w前面已经算过账了。补充一点-w同时影响发送缓冲区和接收缓冲区但实际生效值还受系统 tcp_wmem、tcp_rmem 的最大值限制。如果你的有效窗口始终上不去去检查/proc/sys/net/ipv4/tcp_wmem的第三个数最大值必要时临时调大sysctl -w net.ipv4.tcp_wmem4096 65536 16777216 sysctl -w net.ipv4.tcp_rmem4096 87380 16777216这是测试机上的临时调节不影响业务机器比较安全。-Z--zerocopy是减少数据拷贝用的可以显著降低大流量发送时的CPU占用。在万兆链路测试时如果CPU已经成为瓶颈这个参数值得一试。不过它依赖内核和网卡支持有些老版本内核或非主流网卡驱动下可能报错实测不行就用普通模式结果差异主要在CPU占用率带宽数据差距通常不大。2.3 反向与双向测试-R 和 --bidir 的差别很多人不知道iperf3到底怎么测上传和下载。客户端默认是往服务端方向发送数据也就是说测的是从client到server的“上行”。只看默认方向会漏掉另一个方向的问题。-R--reverse就是让服务端往客户端发送测反方向带宽。你在一台机器上分别跑一次默认和一次-R两个数字对比就能判断链路是否对称。我在一些专线测试中上行和下行差异有时候能到20%以上两边运营商给的光模块速率不一样、中间策略路由方向不一致都能导致这种不对称。--bidir是同时双向打流适合测那些必须双工同时工作的场景比如语音、视频会议链路。但要注意双向同时打流时如果链路是全双工对称的每条方向看到的带宽大约只有单向测试的一半这是正常的。有些人不理解这一点以为产生性能问题其实只是没有意识到同时在压两个方向。2.4 时长与输出解读-t、-i 决定了测试数据的可信度测试时长别太短。默认-t 10秒对于高时延链路TCP拥塞窗口还在爬坡数据根本没跑起来就结束了。我在跨地域链路一般用-t 30在卫星、高丢包链路上甚至用到-t 60。加上-O--omit可以丢弃前N秒的数据跳过慢启动阶段。这个参数很容易被忽略但对结果精度影响很大iperf3 -c 10.10.1.2 -t 30 -O 5 -i 1 -P 4 -w 4M上面的命令含义总共测30秒忽略前5秒每秒打印一条实时数据4条并行流窗口4M。加上-i 1之后你能看到每个时间窗口的吞吐趋势而不是只能看最终平均值。这一点对定位忽快忽慢的问题非常关键。如果最终平均值好看但中间出现长时间的塌陷窗口说明链路存在周期性拥塞或流量整形。输出里有两个关键单位别搞混MBytes是MiB1024×1024字节Mbits/sec是Mbps10^6比特/秒。iperf3报告里还有sender和receiver两组数据分别代表发送端统计和接收端统计。TCP场景下如果接收端吞吐明显低于发送端说明网络中有重传两者差距越大丢包越严重。这个细节下面结果分析专门讲。3. 用UDP打流复杂网络里绕不开的高阶玩法TCP测速会受到拥塞控制算法影响丢包了TCP就会主动降速。这在很多场景下是正确的但也意味着TCP测不出来链路到底能承载多少流量只是在测TCP在这个丢包率下的行为。真要评估链路的原始承载能力、验证QoS限速、测量抖动和丢包率你得用UDP打流。3.1 UDP模式的基本操作-u 配合 -b逼出链路的真实上限UDP模式不需要建立连接不管链路丢不丢包发送端会按指定速率硬发。命令格式是-u加-biperf3 -c 10.10.1.2 -u -b 500M -t 20 -i 1-b 500M表示以500Mbps的速率持续发送UDP报文。这里有个很重要的事UDP模式下的带宽数字不是测出来的结果而是你主动设置的发送速率。实际测出来的结果要看接收端收到了多少、丢了多少。一般我是这样用的先根据链路标称带宽设一个略低于标称值的速率跑一遍看丢包率是不是0。如果没丢再逐步往上加直到出现丢包。这个刚好开始丢包的临界速率才是这条链路真实的转发上限。比如一条标称100M的专线从80M开始打90M、95M、100M、105M逐级加记录每档的丢包率就能画出一条非常直观的链路承压曲线。注意UDP测速时-b指定的速率如果远高于链路能力丢包率会暴涨。收到大面积的丢包比如超过20%接收端看到的带宽甚至可能低于实际出错的水平因为接收端丢包后它的统计会非常难看。中间设备还可能触发保护机制把整条链路暂时性抑制测完之后记得稍等一会儿再跑下一轮。3.2 抖动与丢包率比带宽数值更重要的两个指标UDP模式输出的报告里除了带宽还有两个关键项Jitter抖动和Lost/Total Datagrams丢包数/总数以及最终算出的Lost Percent丢包百分比。抖动描述的是端到端时延的变化程度。对于VoIP、实时视频这类业务抖动比平均延迟更致命。我通常在阈值设置上这么判断本地网络抖动应在1ms以下跨地专线稳定时应在2到3ms以内如果出现5ms以上的抖动说明链路中出现了拥塞排队或限速整形。丢包率的概念是所有搞网络的人都懂的但在iperf3里有个理解差异如果设置了-b 200M而链路只承载了150M那多出来的50M流量是被丢弃的丢包率就会偏高这是你的预期行为。真正需要警惕的是在标称速率之下的丢包。比如100M链路打80M就出现0.1%的丢包了那问题很可能不在带宽容量而在链路质量、光模块、中间设备缓冲配置上。3.3 为什么UDP打流最能反映设备转发和QoS策略的真实情况很多防火墙默认对TCP流量走状态检测对UDP则可能是低优先级转发运营商的QoS限速策略也可能针对UDP有另外一套标记。用UDP打流可以逼出这些问题。举个例子两家企业之间的专线负责的团队说做了带宽保障TCP测速是达标的但UDP一打到某个速率就丢包而且从时间窗口看丢包是均匀分布的这就是典型的流量整形器在起作用——它用令牌桶限制你的PPS或速率超出的部分被直接丢弃而不是缓冲后继续转发。这时候光看带宽数值没用要结合-b速率和丢包率的对应关系去判断。另外UDP小包打流还能测PPS每秒报文数上限。很多设备的转发瓶颈在每秒能处理多少个包而不在每秒能转多少比特。比如同样1Gbps速率用64字节小包打PPS会非常高设备CPU可能直接被打满。这个用小包打流的方式也能暴露。注意具体实现上需要改iperf3的UDP包长用-l指定报文长度iperf3 -c 10.10.1.2 -u -b 500M -l 64 -t 30-l 64表示每个UDP报文的有效载荷为64字节。同一速率下包长越小PPS越高越能压出设备的处理极限。当然这时候吞吐带宽会很难看因为大量报文都是协议头有效吞吐低是正常的关注点应该放在PPS上。计算方式是速率换算成比特后除以报文长IP/UDP头40字节以太网帧开销再除以8。4. 复杂网络场景实战跨防火墙、容器网络、隧道链路的测试要领参数讲透了下面落到场景。我挑三个平时最常碰到的复杂场景把实操过程和注意事项完整写出来。4.1 跨防火墙和多层路由的测试跨防火墙测速比在二层环境要谨慎得多。我在现场执行前会先确认这几件事一是放通端口。iperf3默认端口是5201TCP和UDP模式如果都用同一个端口防火墙策略里要把TCP和UDP的5201都放通。很多防火墙策略默认只放TCPUDP测试时就会一直显示connect failed这问题特别常见。二是会话表老化。如果测试时并行流开得多或者测试时间很长防火墙的并发会话数要够。我先用-P 4 -t 30这样的小规模测试再逐步加量避免一次性并发数太大把防火墙会话表打爆。这个不是夸张我确实遇到过防火墙并发会话数到上限后新连接直接被丢的情况。三是MTU一致性。跨路由场景里如果中间有隧道或MPLS封装端到端MTU很可能小于1500字节。iperf3默认会按1500字节的MSS发送TCP报文但路径上如果某个链路MTU更小且ICMP不可达报文被防火墙拦截就会产生PMTUD黑洞表现为TCP能通但速率极低或者大包全部超时。我习惯在测之前先在两台机器上用ping -M do -s 1472试一下大包通不通不通就说明路径上有MTU限制这时候需要临时降低测试网卡的MTU或者把iperf3的MSS调小但iperf3没有直接改MSS的参数通常是在端口或路由上配置mss clamping。这种问题一旦遇到不改MTU的话测什么都是白测。4.2 容器化网络里的带宽测试现在很多服务跑在Docker容器里直接在容器里跑iperf3和宿主机之间会有差异甚至完全测不准。核心问题在几个点上Docker默认的bridge网络有NAT和端口映射开销。测试时iperf3服务端如果跑在容器里映射端口后数据路径经过了iptables规则、docker-proxy如果开了、veth对、bridge每一层都有处理开销。实测下来同样的物理链路容器内iperf3跑出的速率通常比宿主机低不少。所以容器带宽测试优先使用--network hostdocker run --rm --network host -it --name iperf3-server networkstatic/iperf3 -s docker run --rm --network host -it --name iperf3-client networkstatic/iperf3 -c 10.10.1.2 -P 4 -t 20--network host让iperf3直接使用宿主机的网络栈绕开NAT和veth测出来的数字才接近底层链路的真实水平也方便我们在容器场景里把容器网络开销和物理链路性能两个问题分开看先用host模式测底再用bridge模式测容器网络的额外开销一对比就知道差在哪。CPU限制也要注意。容器默认继承宿主机的CPU配额但如果用--cpus限制了CPUiperf3跑不满是正常的。之前有个案例客户在容器里测速只有300M后来发现容器只分配了0.5个CPU核iperf3单线程跑不满链路其实物理链路完全没问题。这个排查思路很值得记下来。4.3 隧道和叠加网络开销要算清别被数字骗了隧道场景里比如GRE、VXLAN、IPsec带宽测试最容易被数字缩水迷惑。原因很简单隧道的每个报文都要额外携带隧道头原包的MTU被压小了有效载荷占比下降如果流量加密还会消耗大量CPU做加解密。我测IPsec链路时会先量一下隧道封装后端到端的MTU是多少。比如物理接口MTU是1500IPsec封装后可能只剩1400左右。iperf3默认TCP段大小基于路由MTU自动协商但很多中间设备会把TCP MSS钳制到一个固定值这时候iperf3测出的带宽其实是隧道吞吐不完全是物理链路吞吐。要区分这两者可以先在没有隧道的情况下测物理链路再在隧道端到端之间测。两次结果的差值就是隧道开销。如果目的是验证隧道是否正常工作而不是测物理链路极限我一般直接用UDP模式设一个略低于物理带宽的速率跑一遍重点看丢包和抖动。隧道场景下TCP流量可能被PMTUD黑洞干扰UDP模式反而能更稳定地反应转发能力。-b参数控制速率-l参数控制报文长度这两个配合可以把隧道封装后报文是否分片测出来。5. 结果分析不要被好看的数字骗了这些细节才能真正定位问题跑完iperf3拿一行带宽数字就交差了那是最浪费测试的一步。同样的数字背后可能藏着完全不同的网络状态。我个人分析结果时固定按下面几个步骤走。5.1 sender和receiver的差值重传的信号看iperf3最后一段汇总报告如果sender的吞吐高于receiver差值就是网络中丢包重传的量。TCP是可靠传输丢失的报文最终会被重传所以发送端实际发出去了更多数据。在带宽很低的链路上这个现象尤其明显。差值是1%到3%之间链路还能用但已经处于不太稳定的状态差值超过5%基本可以判断链路丢包已经比较严重TCP的拥塞窗口会被频繁砍半吞吐起不来。不过iperf3本身只给你汇总值不告诉你每次重传的分布。要更精确地观察我会在测试时同时跑sar -n EDEV 1或抓包看TCP重传。抓包定位重传是最直接的tcpdump -i eth0 -nn host 10.10.1.1 and host 10.10.1.2 -w /tmp/iperf.pcap然后打开抓包文件看到序列号回退或者连续出现Dup ACK重传和乱序的情况就一目了然了。这里顺手说一句抓包要抓在两端只看一端只能看到一半的流量容易误判。5.2 CPU占用率网络性能测试里的隐性瓶颈iperf3的客户端和服务器在报告末尾都会显示CPU利用率。很多人不看这一段但它往往是带宽不达标的真正答案。如果server的CPU利用率已经接近100%说明接收端处理不过来了瓶颈不在网络在机器。同理client CPU打满发送端成了瓶颈。特别是用UDP打流时CPU开销比TCP更大因为少了TCP卸载的很多机制每报文都要走完整协议栈。如果UDP模式测出来的速率比TCP模式还低且CPU已经打满那几乎可以断定是CPU瓶颈。这时候可以试试-Z减少拷贝或者用更专业的工具比如支持DPDK转发能力的打流工具。多台设备同时测试时还要注意终端上其他进程占用CPU的情况这种东西最容易背锅。提示想确认CPU是不是瓶颈最简单的辅助办法是把-P从1加到4看看吞吐是否成倍增长。如果从1条流到4条流总吞吐涨幅很小且各核CPU已经接近打满那瓶颈就在本机CPU如果吞吐随流数线性增长说明瓶颈在网络侧加大并行流就能继续逼近真实链路带宽。5.3 多轮测试与趋势判断别拿单次结果下结论iperf3单次结果有随机性特别是负载高时TCP拥塞窗口的振荡会让每次结果差异很大。我的习惯是同一个测试条件跑三轮每轮取平均保留最高一轮作为参考上限。如果三次数值差距在5%以内这个结果可信如果差距超过10%说明链路状态波动很大这时候即使平均值好看也要深入排查一下抖动问题。用-i 1输出实时窗口还有一个好处——能看到吞吐曲线是否平稳。正常的稳定链路每秒吞吐应该是一条接近水平的直线顶多有轻微波动。如果曲线呈现锯齿状、周期性塌陷说明链路可能有流量整形、拥塞管理或者底层重传机制在工作这个时候平均值会低估问题的严重程度。我遇到过很多次平均带宽达标但实时窗口频繁跌零的业务投诉最终定位到的是某个中间设备的带宽限速策略配置错误。6. 常见问题与排查技巧实录这些年踩过的坑直接做成速查表下面这组问题是我在项目现场问得最多、也踩得最多的。我直接按现象-原因-解法列出来有需要可以直接照着排查。6.1 连接被拒绝或卡住不动现象可能原因解决方案unable to connect to server服务端没启动、防火墙拦截5201端口iperf3 -s确认监听检查防火墙TCP/UDP 5201放通客户端能连但一直卡在等待中间设备拦截UDP、NAT会话老化UDP模式先小流量试检查中间设备会话超时配置连接建立但瞬间断开服务端版本与客户端不兼容确认两边都是iperf3iperf3和iperf2协议不兼容升级到同版本端口被占用之前测试的服务端进程没退出ss -lntp很多 连接不上 的第一嫌疑其实是防火墙。可以先在客户端和服务端之间用nc -vz 服务端IP 5201测一下端口通不通这一步能快速区分是策略问题还是iperf3本身的问题。6.2 双向测试时两个方向差距过大或双向同时测带宽减半先说减半如果你用了--bidir每个方向速率大约是单向的一半如果链路对称这其实是符合预期的。但如果两个方向差距超过20%那就要查链路面板了比如光模块收发功率不对称、双绞线对绑定策略不同、运营商两条方向走的路径不一致。我处理过的一条专线就是上下行走了不同的物理路由一个方向的时延比另一个高了整整10ms这种链路在长文件传输时性能差异会非常明显。有一个实操细节双向测试时iperf3客户端会同时发起两个方向上的数据收发如果两端机器CPU核数不够收发进程会争抢同一个核造成测出来的两个方向都偏低。如果遇到这种情况用-A参数把服务端接收进程和发送发送端的iperf3绑定到不同CPU核上结果会准很多。6.3 速率远低于预期怎么快速分层定位瓶颈我排查带宽不达标的顺序基本固定按下面走先看CPU利用率排除本机处理能力瓶颈。再跑一轮-P 4 -w 4M -t 30排除单线程和窗口瓶颈。然后用UDP以标称带宽的80%打流看丢包率。如果TCP很差但UDP没问题说明是TCP层丢包/拥塞问题重点排查中间设备的应用层策略如果UDP也丢包说明链路承载能力或中间设备转发能力有问题。最后在两端同时抓包看是重传、乱序、大包分片还是MSS协商异常。按这个顺序走大部分速率不达标问题半小时内能定位到层。别一上来就抓包那是在浪费生命也别一上来就怀疑带宽买少了那是在给甲方增加恐慌。6.4 iperf3的局限性与替代方案最后说句公道话iperf3不是万能的。它在单机性能测试、链路验证场景里非常顺手但有些场景它确实不合适。比如iperf3基于单线程事件模型一个连接几乎对应固定CPU天然难以测满基于多队列的高性能DPDK转发链路再比如iperf3没有内置的HTTP代理、TLS等应用层模拟能力测应用层性能还得靠别的工具。替代方案要看具体场景qperf和nuttcp也走类似思路但支持RDMA等高级特性需要模拟真实HTTP流量时可以用专业的压测工具要做长时间稳定性验证iperf3的-t 600甚至更长时间完全够用。日常网络层带宽验证我仍然推荐iperf3省事、快、生态广掌握好参数和解读方式它基本不会误事。还有个小技巧挺多人都不知道iperf3支持-J输出JSON格式结果写脚本批量跑测试、自动收集数据时特别方便。我一般用一段简单的循环把不同-P值、不同-b速率的结果落盘成JSON然后统一分析这样比人眼盯屏幕靠谱得多。for p in 1 2 4 8; do iperf3 -c 10.10.1.2 -P $p -t 30 -J result_${p}.json done跑完之后用 jq 解析关键字段吞吐、丢包、CPU 一项项看整个链路的性格就清楚了。这也是我在复杂网络项目里最常用的收尾手段。