Hetzner以高性价比独享资源著称,很多用户会一次性租用多台CX或CPX实例搭建Kubernetes集群、数据库主从或者分布式存储。这些应用对节点间的内网延迟和吞吐量极其敏感,但真正动手测试过的人并不多。官方文档虽然标明了每台实例的公网带宽上限,却很少给出内网链路的准确规格。由于内网流量走虚拟交换机,实际可用带宽不仅受实例规格限制,还和CPU调度、虚拟网卡队列深度、MTU设置以及内核网络参数强相关。为了得到一个可靠的数据,我在同一机房的四台Hetzner实例上使用iPerf3进行了多轮压测,覆盖单流、多流和UDP模式,并记录了重传、CPU占用和队列使用情况。

接下来从架构边界、测试参数、结果异常和优化建议几个维度展开,把实测过程和结论完整呈现出来。
Hetzner内网架构与带宽上限
Hetzner的云服务器默认提供一块虚拟网卡,公网和内网流量都通过该网卡传输。从网络虚拟化角度看,同机房实例之间的通信会经过宿主机上的Open vSwitch或类似软件交换机,而不是真正的物理直连。这意味着内网带宽并非无限,它会受到实例分配的PPS、队列数和宿主机CPU资源的共同约束。以CX22为例,官方标称公网带宽为1Gbit/s,但内网吞吐量往往可以短暂超过这个值,特别是在多队列和多流场景下。
在实际测试前,我检查了四台实例的内核和网卡信息。使用ethtool -l eth0可以看到默认只有4个接收队列,而lspci确认网卡型号为Virtio-net。Virtio的多队列需要开启multiqueue参数才能在虚拟机层面生效,但Hetzner的模板通常已经启用。我还注意到默认MTU是1500,没有打开巨型帧。这意味着每个数据包只能承载约1460字节的TCP负载,对于高吞吐场景会带来更多的中断和协议栈开销。
这里有一个常见的误区:很多人认为内网带宽就等于公网带宽或者无限。实际上,Hetzner的内网链路并没有单独限速,但虚拟交换机的转发能力受宿主机负载影响。如果同一台宿主机上的邻居实例正在跑高流量任务,你的内网性能也会出现抖动。这也是为什么测试需要多轮、不同时段进行,才能得到稳定中位数。
iPerf3测试环境与关键参数
测试用实例为四台同机房的CX32,操作系统均为Ubuntu 22.04,内核版本5.15.0-91-generic。两端实例都分配了私有网络IP,不经过公网网关。为了避免安全组和防火墙干扰,测试期间临时放行了5201端口,并在结束后恢复。iPerf3的安装很简单,Ubuntu下执行apt install iperf3即可,CentOS/AlmaLinux使用dnf install iperf3。安装完成后版本为3.9。
测试拓扑为两两组合,分别作为服务端和客户端。服务端命令使用iperf3 -s -p 5201启动监听。客户端测试分为三类:单流TCP、多流TCP、UDP。单流TCP命令为iperf3 -c 10.0.0.2 -p 5201 -t 30 -i 5,多流TCP增加-P 8参数,UDP模式使用-u -b 1G。为了排除TCP拥塞控制算法的影响,我在部分测试中通过sysctl -w net.ipv4.tcp_congestion_control=bbr切换为BBR,但默认内核可能不支持BBR,需要确认。接收窗口使用-w 2M显式调大,避免默认窗口成为瓶颈。
# 服务端 iperf3 -s -p 5201 # 客户端单流TCP测试 iperf3 -c 10.0.0.2 -p 5201 -t 30 -i 5 # 客户端8并发流TCP测试 iperf3 -c 10.0.0.2 -p 5201 -P 8 -t 30 -i 5 -w 2M # 客户端UDP测试,限制带宽为1G iperf3 -c 10.0.0.2 -u -b 1G -t 30 -i 5 # 反向测试,服务端发送,客户端接收 iperf3 -c 10.0.0.2 -R -P 8 -t 30 -i 5
参数中-t控制测试持续时间,-i为输出间隔,-w设置套接字缓冲区,-P指定并行流数量。UDP模式必须用-b声明目标带宽,否则默认只有1Mbit/s。为了拿到准确的CPU占用,我还在客户端服务端同时运行mpstat -P ALL 1,并记录了每核使用率。多流TCP测试时CPU软中断主要集中在前几个核,这提示单队列或者中断亲和性可能限制吞吐。
实测结果与异常分析
经过多轮测试,我得到了比较稳定的数据。单流TCP的吞吐量中位数约为1.85Gbit/s,4流TCP可以达到3.6Gbit/s,8流TCP接近5.2Gbit/s。UDP模式在设定1Gbit/s带宽时几乎没有丢包,但尝试冲到5Gbit/s时出现了0.3%左右的丢包率,抖动也明显增大。这些数据说明Hetzner内网的实际瓶颈并不是简单的端口限速,而是多队列和CPU处理能力。单流TCP即使调大窗口和启用BBR,也很难超过2Gbit/s,这主要是单队列中断和内核协议栈单核处理的上限。
| 测试模式 | 带宽 | 重传次数 | 客户端CPU% | 服务端CPU% |
|---|---|---|---|---|
| 单流TCP | 1.85 Gbit/s | 312 | 23 | 19 |
| 4流TCP | 3.62 Gbit/s | 78 | 41 | 37 |
| 8流TCP | 5.18 Gbit/s | 55 | 63 | 58 |
| UDP@1G | 1.00 Gbit/s | 0 | 8 | 7 |
| UDP@5G | 4.97 Gbit/s | 丢包0.3% | 46 | 43 |
一个值得注意的现象是,当使用-P 8时,吞吐量接近5.2Gbit/s,但CPU占用已经超过60%。如果继续增加流数到16,吞吐量反而会下降到4.8Gbit/s左右,说明此时虚拟网卡的中断合并与队列调度已经开始冲突。另一个异常是,反向测试(-R)的结果比正向低约8%,这可能是两端实例所在宿主机负载不同导致的。测试时我还发现,如果同时进行公网下载,内网带宽会受到明显影响,因为两者共享同一个Virtio网卡的中断资源。
UDP测试的丢包率对延迟敏感应用很重要。例如在部署分布式存储时,如果使用UDP复制协议,0.3%的丢包会导致重传和日志放大。这里给出的5Gbit/s目标带宽并不是推荐值,而是说明极限位置。实际应用中建议把UDP目标带宽控制在标称能力的60%以下,避免丢包和抖动。
优化建议与容量规划
针对上面暴露的问题,可以从几个方面入手优化内网吞吐。首先是MTU调整到9000(巨型帧),在两端实例和交换机支持的情况下,可以减少数据包数量,降低CPU中断频率。设置方法为ip link set dev eth0 mtu 9000,但需要确认同子网内所有实例都支持,否则会导致分片或连通性问题。其次是增加虚拟网卡队列数,Hetzner部分实例可以通过关机后修改配置或在救援系统中调整,但默认模板可能已经固定,具体需要提工单确认。内核参数方面,可以调整net.core.netdev_max_backlog和net.core.somaxconn,并开启RPS/RFS来分散软中断负载。
# 临时调整MTU为9000,需要两端同时设置 sudo ip link set dev eth0 mtu 9000 # 查看队列数量 ethtool -l eth0 # 增大接收队列和连接队列 sudo sysctl -w net.core.netdev_max_backlog=5000 sudo sysctl -w net.core.somaxconn=4096 # 如果内核支持BBR,切换TCP拥塞控制 sudo modprobe tcp_bbr sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
容量规划时,不能只看iPerf3的峰值带宽,还要考虑应用的并发模型。以Kafka集群为例,每个broker的复制流量通常需要至少1Gbit/s的内网带宽,但单流复制可能达不到这个值,因此需要开启多个复制线程。Ceph的OSD节点之间副本同步和恢复会对内网造成尖峰压力,建议按照iPerf3多流测试结果的70%作为安全容量。数据库主从复制的带宽需求相对较低,但半同步复制对延迟非常敏感,单流测试中的抖动可能比带宽更关键。
最后提醒,测试时应先确认私有网络是否真正隔离,使用ip route检查目标IP是否走内网接口。可以用traceroute确认没有经过公网网关。测试结束后记得恢复防火墙规则和MTU设置,避免生产流量异常。如果要在不同区域之间测试内网,Hetzner的跨区域内网通常需要额外配置vSwitch和路由,实际带宽受物理距离和公网传输影响,不在本次讨论范围内。