
最近在帮人调一个办公网络的问题两台服务器每天备份往对方拷贝一个大约 20GB 的数据包实际速度只有 30MB/s 左右。服务器是千兆网卡硬盘也是 SSD理论上应该跑到 110MB/s 以上。排查了一圈网线换了、网卡驱动重装了、SMB 参数也调了最后用 iperf 直接打流量才发现问题出在交换机端口上——某个端口协商到了百兆直接把吞吐量限制死了。如果没有 iperf这种问题你很难快速定位到底是哪一层出了问题。内网测带宽这件事iperf 几乎就是行业标准工具。CentOS 9 这种新系统上虽然很多基础工具都内置了但 iperf 不一定默认可用而且默认仓库里的版本也不一定新。这阵子我在 CentOS 9 上完整走了一遍安装、测速、调优和排错把实际结果和踩过的坑整理出来希望能节省你不少时间。1. 为什么内网测速要用 iperf先把场景和原理搞清楚1.1 文件拷贝测速为什么骗人很多人的第一反应是测内网带宽直接拷贝个大文件不就行了。但实际测过就会发现文件拷贝的速度受太多因素干扰。磁盘读写性能、文件系统缓存、SMB/NFS 协议开销、CPU 处理能力、网卡驱动、网络延迟任何一个瓶颈都会体现在拷贝速度里。你测出来的数字是一个“综合性能”而不是“链路本身的带宽”。我曾经在一台机器上拷贝大文件表面速度能稳定在 95MB/s感觉很不错。结果后期任务一多速度立刻掉到 40MB/s又找不出原因。后来用 iperf 单独打流才发现链路本身只能跑到 98MB/s 左右的 TCP 吞吐量接近千兆线速问题不在网络而在于文件读写或者协议占用的 CPU 过高。这就说明文件拷贝测的是“系统整体性能”而 iperf 测的是“网络链路能力”。1.2 iperf 的工作原理用一个极简模型看透吞吐量iperf 的核心思路很简单客户端向服务端持续发送一段数据流服务端接收并统计单位时间内收到的数据量从而得出带宽数值。它不关心你的磁盘、文件系统、任务调度它只关心数据从网卡到网卡之间的传输能力。以 TCP 模式为例客户端会调用send()不断发送数据服务端调用recv()接收统计接收的字节数除以测试时间得到每秒吞吐量。同时还会统计 TCP 重传retr、乱序等指标。UDP 模式下客户端会以固定码率发送 UDP 报文服务端统计接收速率和丢包率用来判断网络是否稳定、是否存在拥塞或丢包。这个“隔离”特性非常重要。内网带宽测试的目的就是验证物理链路、交换机、网卡、协议栈是否正常为后续应用性能调优提供基线。如果你把文件拷贝慢的问题直接归咎于网络很可能方向就错了反过来如果 iperf 测出来的吞吐量远超实际应用速度那你应该去检查应用层、存储层而不是继续折腾网络。1.3 iperf 2 还是 iperf 3CentOS 9 上该选谁iperf 有 2.x 和 3.x 两个大版本两者并不兼容。iperf3 由 ESnet 主导开发重新设计了架构支持更多的报告指标、多线程、JSON 输出等功能是目前绝大多数系统和工具链默认的选择。CentOS 9 的软件仓库里通常提供的是 iperf3这也是我在实际项目里推荐使用的版本。如果你要跟老设备对接或者维护老脚本可能用到 iperf2。但新部署环境建议直接用 iperf3因为它的参数更统一文档更完善。我这里所有实测都是基于 iperf3 完成的。注意iperf2 的测速结果跟 iperf3 在同等环境下会有差异尤其在高带宽、多线程场景下iperf3 对 UDP 的处理方式也不同所以横向对比时要保证两端版本一致。2. CentOS 9 安装 iperf3仓库优先源码兜底2.1 第一件事确认系统版本和默认仓库里有没有 iperf3安装之前先确认你手上确实是 CentOS 9。这个命名有点历史经典 CentOS 8 提前退休后CentOS 9 实际就是 CentOS Stream 9它是 RHEL 9 的上游开发版dnf 仓库结构和 RHEL 9 非常接近。你可以看/etc/redhat-release或者运行cat /etc/redhat-release正常会看到类似CentOS Stream release 9的输出。如果你用的是云厂商提供的 CentOS Stream 9 镜像也是一样的道理。然后检查仓库里有没有 iperf3dnf list iperf3如果输出显示有可用包直接安装即可。如果在某些精简版系统里没有默认提供 iperf3也不用纠结后面有源码编译的办法。2.2 一条命令装上 iperf3如果仓库里有大多数情况下CentOS Stream 9 的仓库里会带 iperf3。安装命令dnf install -y iperf3装完验证版本iperf3 -v我这边装出来是类似iperf 3.9的版本注意 iperf3 的版本号不带.0输出首行会显示iperf 3.9或iperf 3.x。如果你对版本没有苛刻要求用默认仓库的版本完全足够日常测速。默认仓库的好处是由系统维护安全更新及时不用担心动态库依赖问题。2.3 源码编译安装几个容易忽略的细节如果你需要最新的 iperf3比如要用到 3.14 版本里的某些新参数或者你的仓库里根本没有 iperf3那就走源码编译。整个过程不复杂但有几个细节值得注意。先安装编译工具和依赖dnf install -y gcc make然后从官网下载源码。以 iperf 3.14 为例wget https://downloads.es.net/pub/iperf/iperf-3.14.tar.gz tar xf iperf-3.14.tar.gz cd iperf-3.14 ./configure make -j$(nproc) make install编译完成后二进制默认放在/usr/local/bin/iperf3。这里有个坑/usr/local/bin不一定在当前用户的 PATH 里特别是普通用户登录时。你可以直接用绝对路径运行或者确认一下 PATH/usr/local/bin/iperf3 -v源码编译默认安装到/usr/local动态库会放到/usr/local/lib。如果运行iperf3时提示找不到libiperf.so.0说明动态库路径没配置好这个问题后面我会专门写一条排错记录。2.4 安装完成后怎么验证以及动态库问题不管用哪种方式装完之后都要验证两个点版本是否正常iperf3 -v动态库是否能加载直接运行iperf3 -s或者iperf3 -c 127.0.0.1可以用本机回环测试快速验证安装是否可用iperf3 -s -p 5201 iperf3 -c 127.0.0.1 -p 5201回环测试通过说明程序本身没问题。后面对内网机器测速时如果连接不上就是网络层面的问题而不是安装问题。3. 内网带宽测试的标准姿势服务端、客户端、参数组合3.1 最简单的一次 TCP 测速只需要两条命令假设你的内网有两台 CentOS 9 机器A 当服务端B 当客户端。服务端上先启动iperf3 -s默认监听 5201 端口。客户端上执行iperf3 -c 192.168.1.10默认测试 10 秒结束后会输出完整报告。这是最简单的用法但也是最容易出错的地方因为 iperf3 的默认参数是单线程对于高带宽链路可能测不满。3.2 参数详解-P -R -w -u 到底在干什么实际内网测速时我几乎不会只用默认参数。下面这几个参数是最常用的-P, --parallel指定并行连接数。比如-P 4表示用 4 个 TCP 连接并行测试。单线程很难跑满多核 CPU 的网卡处理能力特别是万兆环境一般建议从 4 开始试。-R, --reverse反向测试即服务器端发送数据客户端接收。有些场景下上行和下行的吞吐量差异明显可以用来判断网卡、交换机端口或驱动是否有方向性问题。-w, --window指定 TCP 窗口大小。例如-w 1M设置窗口为 1MB。默认窗口可能不够大特别是高带宽高延迟链路适当加大窗口能显著提升吞吐量。-u, --udp使用 UDP 测试。UDP 测速用来评估链路的稳定性和最大可承载速率因为 UDP 不关心拥塞控制能直接暴露丢包。-t, --time测试总时长默认 10 秒。内网测试建议 15 到 30 秒太短测不出抖动太长耽误时间。-O, --omit忽略前 N 秒的数据用于跳过 TCP 慢启动阶段得到稳定后的吞吐量。组合示例iperf3 -c 192.168.1.10 -P 4 -t 15 -O 2这条命令的意思是用 4 个并发流测试 15 秒忽略前 2 秒的预热数据。3.3 更规范的内网测速流程TCP 起步UDP 辅助我的习惯是先测 TCP再测 UDP。TCP 测速反映的是实际用户体验UDP 测速反映的是链路硬指标。TCP 测速流程服务端启动iperf3 -s从客户端用默认参数测一次iperf3 -c 服务端IP -t 15用 4 线程再测一次iperf3 -c 服务端IP -P 4 -t 15反向测试iperf3 -c 服务端IP -R -P 4 -t 15UDP 测速流程iperf3 -c 服务端IP -u -b 100M -t 15-b指定目标发送带宽。如果链路质量好丢包率应该很低。如果丢包率超过 1%说明链路存在拥塞或交换机的缓冲不足。实测的时候我会把 TCP 和 UDP 结果分开记录因为两者含义不同TCP 结果是链路实际能提供的可靠吞吐量UDP 结果是链路能不能稳定跑满某个带宽。3.4 实测端口选择与防火墙放行的正确操作iperf3 默认使用 5201 端口。如果多组测试同时进行可以用-p指定不同端口避免互相干扰服务端iperf3 -s -p 5202客户端iperf3 -c 服务端IP -p 5202CentOS 9 默认开启了 firewalld如果不放行端口客户端会连不上。放行前先确认当前 zonefirewall-cmd --get-default-zone一般是public。然后放行端口firewall-cmd --permanent --add-port5201/tcp firewall-cmd --permanent --add-port5201/udp firewall-cmd --reload注意UDP 测试也需要放行 UDP 端口很多人只加了 TCP结果 UDP 测速的时候丢包接近 100%。另外源码编译安装的 iperf3 服务端如果收到连接会自己创建套接字不需要额外放行出方向。4. 千兆内网实测数据长什么样怎么读才不算白测4.1 测试环境两台 CentOS 9普通千兆交换机我这里的实测环境很简单两台都是 CentOS Stream 9网卡是 Intel 千兆卡接同一个普通交换机。没有链路聚合没有巨型帧就是最典型的办公室环境。两台机器通过静态 IP 互联网卡协商速率确认是 1000Mbps。先看网卡协商ethtool enp0s25 | grep Speed4.2 命令与实测结果摘录服务端启动iperf3 -s客户端执行默认单线程测试iperf3 -c 192.168.1.10 -t 15结果的关键部分摘录[ ID] Interval Transfer Bitrate [ 5] 0.00-15.03 sec 1.82 GBytes 1.04 Gbits/sec sender [ 5] 0.00-15.03 sec 1.82 GBytes 1.04 Gbits/sec receiver可以看到单线程就跑到 1.04 Gbits/sec已经接近千兆线速。这个数字是 Gbits/sec不是 MBytes/sec。换算成常用单位就是 130MB/s 左右。如果是实测你可能会看到 940Mbps 到 990Mbps 之间取决于协议开销和网卡驱动这个范围都算正常。如果换 4 线程iperf3 -c 192.168.1.10 -P 4 -t 15结果大概率还是 1Gbps 左右因为千兆就是瓶颈再加线程也不会超过物理链路。如果多线程之后吞吐量反而上升很多说明单线程已经受限于某个因素比如 CPU 单核性能或者 TCP 窗口。4.3 结果解读bandwidth、retr、CPU 利用率与线速的关系iperf3 报告里最核心的是sender和receiver两行的Bitrate。正常情况下两者应该非常接近差异在 1% 以内。如果 sender 比 receiver 高出一截说明网络存在拥塞或重传receiver 才是你真正能拿到的速率。重传指标在报告底部Retr如果重传数持续增长说明链路有丢包或者队列溢出。对千兆内网来说重传率超过 0.1% 就该引起注意。报告还会显示本地 CPU 利用率CPU Utilization: local/sender 2.1% (0.2%u/1.9%s), remote/receiver 3.8% (0.3%u/3.5%s)如果 CPU 利用率接近 100%说明瓶颈可能在 CPU。相反如果链路吞吐量上不去而 CPU 使用率很低说明有其他因素限制比如窗口、网卡参数或者交换机限速。4.4 把结果变成报告JSON 输出和多次测试取最优内网带宽测试一般要测多次取最优值避免偶发因素干扰。iperf3 支持 JSON 输出方便脚本处理iperf3 -c 192.168.1.10 -P 4 -t 15 -J result.json生成的 JSON 里包含完整的带宽、重传、CPU 使用率、每秒详细记录等可以用 jq 提取关键字段jq .end.sum_received.bits_per_second result.json多次测试时我习惯测三组每组间隔几十秒取 receiver 带宽最大值。如果三组数据波动超过 15%说明网络不稳定需要进一步排查。5. 带宽不达标按这个顺序排查别一上来就怪网线5.1 从服务端日志和客户端输出先定位表象当测速结果明显低于预期时先别急着换线。看两样东西客户端的 sender/receiver 差异、以及服务端输出的实际接收速率。比如客户端显示发送了 500Mbps服务端只收到 300Mbps那说明数据在中间丢了问题可能出在交换机或物理链路。如果服务端和客户端都只跑到 300Mbps那更可能是链路协商、网卡或发送端限制。先跑一条 UDP 测试来量化丢包iperf3 -c 服务端IP -u -b 100M -t 10如果丢包率很高优先检查物理链路和中间设备。5.2 防火墙与端口最常见的第一道坑CentOS 9 默认防火墙拦截外部端口。如果你从其他机器连不上 5201记住这三个步骤服务端确认监听ss -nltp | grep 5201客户端确认能通端口nc -vz 服务端IP 5201服务端放行端口并 reload。有一个容易忽略的点如果你用了 IP 白名单或区规则即使端口放行了来源主机可能也被拒。可以用firewall-cmd --list-all查看当前完整规则。5.3 物理层检查协商速率、网线质量、交换机端口协商速率不达标是内网测速最常见的物理层问题。用ethtool查看ethtool eno1重点看Speed: 1000Mb/s和Duplex: Full。如果显示Speed: 100Mb/s先换网线、换交换机端口再排查网卡配置。网线可以直观压一下水晶头看接触是否牢固。还有一种情况是网卡强制设置了百兆全双工而交换机是口自动协商可能出现双工不匹配导致性能下降还不稳定。建议统一使用自动协商不要手动强制。交换机端也可以查一下端口统计的错包率。如果条件允许把两台机器直连中间不经过交换机再测一次。直连能跑到线速说明交换机或中间链路有问题直连也慢那就是网卡或网线的问题。5.4 传输层调优多线程、TCP 窗口、内核缓冲排除物理层之后再看传输层。iperf3 单线程可能跑不满高带宽链路的常见原因有单个 TCP 连接受窗口限制最大吞吐量约等于窗口大小除以往返时延。内网 RTT 很低但是某些网卡中断处理在单核上也会限制单线程性能。解决办法是加-P 4用多线程。如果多线程后吞吐量几乎线性增加那基本确定是单流瓶颈而不是链路问题。如果多线程提升不大尝试调整 TCP 窗口iperf3 -c 服务端IP -P 2 -w 1M -t 15还可以调整系统内核缓冲参数修改/etc/sysctl.conf增加net.core.rmem_max 134217728 net.core.wmem_max 134217728 net.ipv4.tcp_rmem 4096 87380 134217728 net.ipv4.tcp_wmem 4096 65536 134217728然后sysctl -p生效。这个操作对 iperf 测试和真实应用都有好处但要注意别设置过小导致 TCP 窗口无法扩展。5.5 端到端瓶颈CPU 和高频小包处理能力最后一个容易忽略的瓶颈是 CPU。千兆网络一般没问题但如果你在万兆环境或者频繁处理大量小包CPU 的收包能力会成为瓶颈。iperf3 的 CPU 报告会告诉你本地和远端处理使用的百分比。如果单线程测试时某个核跑到 100%但总吞吐量不足可以试试开启网卡多队列功能。用lspci查网卡型号用ethtool -L eno1 combined 4调整队列数。对于忙于软件中断的场景设置 RSS 多队列能显著改观。我自己遇到过一次VirtIO 网卡在虚拟机里默认队列只有 1iperf3 单线程吞吐只有 300Mbps把队列数调到 4 并绑上多核中断马上跑满。这个经验也分享给你别把问题都怪到物理机上。6. 我在 CentOS 9 上实际踩过的坑排错链路还原6.1 源码装完启动报错 libiperf.so.0一条软链接解决用源码编译安装 iperf3 后直接在命令行执行iperf3 -v可能会遇到这个错误iperf3: error while loading shared libraries: libiperf.so.0: cannot open shared object file: No such file or directory原因很简单libiperf.so.0安装到了/usr/local/lib但系统默认不会从这个目录加载动态库。解决办法是让动态链接器知道这个路径。创建配置文件echo /usr/local/lib /etc/ld.so.conf.d/iperf3.conf ldconfig再运行iperf3 -v就正常了。如果不想改系统配置也可以用环境变量export LD_LIBRARY_PATH/usr/local/lib但建议用ldconfig因为这个动态库不会只影响 iperf3以后其他程序安装到/usr/local/lib时也会受益。6.2 服务端明明在跑客户端就是连不上端口与 SELinux我在一台 CentOS 9 上启动iperf3 -s用ss -nltp确认确实在监听 5201但客户端连接报Connection refused。排查第一步我确认了防火墙已经放行。结果发现是 SELinux 拦截了非标准端口绑定不是我这里是连默认端口也拒了因为 SELinux 对网络服务的上下文有默认策略。临时关闭 SELinux 试试setenforce 0如果问题消失那就是 SELinux 策略的问题。长期使用不建议保持 Permissive可以用audit2why或ausearch查看具体拦截记录ausearch -m avc -ts recent确认是监听端口的类型问题后给 iperf3 二进制设置正确的上下文或者添加自定义策略模块。对于内网测试这种临时场景也可以使用非标准端口并让 SELinux 放行相应端口但更省事的做法是确认这台机器是专用测试机后调整策略。6.3 单向测速异常反向就正常网卡驱动或中断亲和性有次实测A 作为服务端、B 作为客户端正向测只有 300Mbps加上-R反向测又恢复正常 900Mbps。这种方向性差异很迷惑。我先检查交换机端口配置两个口都是千兆全双工排除物理层。然后查 A 机网卡是否有多队列以及中断是否都落在同一个 CPU 核上。通过cat /proc/interrupts查看网卡中断分布发现 eno1 的中断几乎全部集中在 CPU0 上。测试时 CPU0 已经接近 100%吞吐自然被压住。解决办法是用set_irq_affinity脚本或者手动分配中断到不同核心恢复多队列并行处理。之后单向测速就恢复到 900Mbps 以上。这个问题在物理机上比较少见在虚拟机和某些板载网卡上更容易出现。如果遇到单向异常第一时间看中断分布和处理 CPU 占用。6.4 快速诊断清单5 分钟从零开始定位问题最后分享一个我常用的快速诊断清单碰到内网带宽不达标按顺序执行确认两端 iperf3 版本一致iperf3 -v确认服务端在监听ss -nltp | grep iperf确认防火墙放行firewall-cmd --list-ports确认网卡协商速率ethtool 网卡名测 UDP 丢包iperf3 -u -b 100M -t 10测多线程 TCPiperf3 -P 4 -t 15 -O 2直连两台机器再测一次排除中间设备看 CPU 利用率和中断分布整套走下来要么已经定位出问题要么你就会发现自己需要的数字已经拿到后续调优也有据可依。iperf3 本身不是一个复杂的工具但你真的读懂它的输出并会用参数时它就能成为内网排障里最可靠的一把尺子。