外观
网络性能:multiqueue 与 vhost-net
大多数虚拟机的网络性能问题根本不在 multiqueue,而在网卡型号选错了。这篇先说清楚默认情况下已经拿到了什么,再讲 multiqueue 什么时候才值得开。
先确认网卡型号和瓶颈位置
sh
# 客户机内部,确认使用的是 virtio_net 驱动而不是模拟网卡
ethtool -i eth0
# 宿主机:确认瓶颈是不是网络
iftop 或 nload虚拟机网卡型号选 VirtIO (paravirtualized) 而不是默认的 Intel E1000,是网络性能里收益最大的一步,做完这一步大多数场景已经够用。continue 往下看之前,先确认瓶颈真的在网络吞吐/延迟,而不是客户机 CPU 被别的事占满,或者物理网卡/交换机本身只有 1G。
vhost-net:默认已经在用的加速
VirtIO 网卡的收发包处理,默认由宿主机内核里的 vhost-net 内核线程完成,而不是走用户态 QEMU 进程转发。这是 PVE 的默认行为,不需要手动开启,也没有额外的配置项。它把原本"客户机 → QEMU 用户态 → 内核网络栈"的路径缩短成"客户机 → 内核 vhost 线程 → 内核网络栈",减少了一次用户态/内核态切换。
选了 VirtIO 网卡,这部分收益就已经拿到了。
multiqueue:让多个 vCPU 同时处理网络中断
默认情况下,一块虚拟网卡的收发包由一个队列处理,对应宿主机上的一个 vhost 内核线程。如果客户机有多个 vCPU,但网络流量集中在一个队列上,这个队列所在的那一个 vCPU 会先达到瓶颈,即使其他 vCPU 还空闲。
multiqueue 让一块网卡开出多个收发队列,分散到多个 vCPU 处理。
| 适用条件 | 代价 |
|---|---|
| 虚拟机承担大量并发连接的角色:软路由、反向代理、繁忙的 HTTP/数据库服务;且虚拟机有多个 vCPU | 队列数越多,宿主机和客户机的中断处理开销越大,流量越大开销越明显;单队列打不满的低负载场景开多队列没有收益,纯粹增加负担 |
multiqueue 不是"开了就一定更快"
官方文档明确:队列数设得比实际能用上的多,只会随着流量增加而线性增加宿主机和客户机的 CPU 负载,吞吐不一定跟着涨。只给真正要处理大量并发连接的虚拟机开,数值不要超过该虚拟机的 vCPU 核心数。
怎么开
虚拟机 → Hardware → 网络设备 → Edit → Multiqueue,填入队列数(建议等于该虚拟机的 vCPU 核心数),或者宿主机 shell:
sh
# <vmid> 是虚拟机编号,<n> 是队列数,建议等于 vCPU 核心数
qm set <vmid> --net0 virtio=<mac>,bridge=vmbr0,queues=<n>改完关机再开机才会生效(网卡设备的队列数是 QEMU 启动时确定的),Reboot 不够。
再到客户机内部把网卡的实际队列数调上去,否则宿主机这边开了队列客户机也用不上:
sh
# 客户机内部(Linux),把 ensX 换成实际网卡名,X 是队列数
ethtool -L ens18 combined <n>影响范围与回退
调整网卡设备需要虚拟机完整重启一次,期间这台虚拟机的网络会短暂中断。回退时把 queues= 去掉(或改回 1)并重启虚拟机即可,不涉及数据丢失,只是短暂的服务中断。
MTU:另一个常被忽略的选项
如果内网环境支持巨型帧(jumbo frame),把虚拟机网卡和对应网桥的 MTU 一起调大(例如 9000),能降低大流量传输时的每包开销。这项和 multiqueue 是两回事,而且网桥、物理交换机、虚拟机网卡三处的 MTU 必须一致,否则会出现连接建立正常但大包传输失败的诡异现象。详细配置见 MTU 与巨型帧。
检查结果
sh
# 宿主机:确认队列数写入配置
qm config <vmid> | grep net
# 宿主机:确认对应的 vhost 线程数量
ps -eLo pid,comm | grep vhost客户机内部:
sh
ethtool -l ens18 # 确认 Combined 的当前值和最大值一致用 iperf3 在客户机之间(或客户机与宿主机之间)跑一次吞吐测试,对比开启 multiqueue 前后的数据,并观察宿主机整体 CPU 占用有没有明显上升(见基准测试方法)。
常见问题
开了 multiqueue 但速度没变化。 检查客户机内部是否也用 ethtool -L 把队列数调上去了——宿主机和客户机两边都要配置,只改一边没有效果。也可能是瓶颈本来就不在网络队列数上(单一 TCP 连接的吞吐通常受限于单队列本身的处理能力,而不是队列数量)。
改了队列数之后 CPU 占用明显升高,吞吐却没提升。 说明这台虚拟机的场景不适合 multiqueue(流量不够大、并发连接数不够多),改回默认的单队列。
虚拟机之间互通变慢。 先确认不是 MTU 不一致导致的分片问题,再检查防火墙规则和限速设置,见客户机网络。