虚拟机性能优化实战:CPU绑核、大页内存与网络多队列调优指南

发布时间:2026/10/21 6:43:41
虚拟机性能优化实战:CPU绑核、大页内存与网络多队列调优指南 最近好多搞虚拟化和容器的人跟我抱怨同一个问题虚拟机配置看着挺高CPU、内存都给足了可业务跑起来就是慢接口延迟动不动几十毫秒压力稍微一大就卡成PPT。尤其是一些需要毫秒级响应的业务比如支付、交易、实时风控这类场景对延迟特别敏感虚拟化层的任何一点开销都会被放大。我自己在前段时间接手过一个类似的调优项目某模拟业务系统跑在虚拟机里压测时接口P99延迟一度到了45ms优化到最后一轮压测才2-3ms。中间踩了不少坑也积累了很多经验。这篇文章就把整套思路和实操过程整理出来完整讲清楚虚拟机性能优化到底怎么入手从资源瓶颈定位、CPU绑核、内存大页到磁盘I/O和网络多队列全部给你盘一遍。适合虚拟化平台运维、云平台架构师、后端开发只要你手里的业务跑在虚拟机上并且对延迟有要求这篇文章都值得看完。1. 先定位瓶颈别让性能优化变成盲人摸象1.1 资源瓶颈四象限CPU、内存、磁盘、网络调优最容易犯的错就是上来直接一顿操作看到配置就给虚拟机加CPU、加内存结果加完发现业务照样慢。因为虚拟机性能问题往往不是单一资源导致的你加的恰好不是它缺的。我的习惯是先把瓶颈分成四个象限CPU、内存、磁盘I/O、网络。每类瓶颈都有比较典型的特征信号对照着看就能缩小范围。瓶颈类型典型信号容易误判的点CPUGuest内负载高但物理机CPU占用不高CPU steal时间高runqueue长以为是应用代码问题实际是超分太狠或绑核没做内存Guest内swap频繁申请大内存失败NUMA跨节点访问严重以为是业务内存泄漏实际是宿主大页耗尽或内存气球回收太激进磁盘I/Oiowait高、io延迟大、队列深度堆积但CPU空闲以为是存储设备问题实际是镜像格式、缓存模式、iothread配置不对网络软中断占比高、单队列中断集中、TCP重传增多、P99抖动以为是应用层协议慢实际是多队列没开或者vhost线程漂移这里我想重点强调一下 CPU steal time。这个指标是宿主机上其他进程抢占物理CPU导致虚拟机等待的时间如果在mpstat里看到%steal长期超过5%真凶多半在宿主机侧要么超分过狠要么物理核被其他负载抢了。曾经有个案例业务方在Guest里查了三天代码最后发现是同一台宿主机上十几个VM都在跑定时任务物理核被抢得厉害。所以调优之前一定要看宿主视角而不是只在Guest里面转。1.2 一套可复用的性能摸底流程定位资源瓶颈不能靠猜要有一组可控的测量方法。我一般按下面这套流程来摸底不管什么业务都能套用找一个业务低峰期或者直接搭一套与生产配置一致的隔离环境避免其他负载干扰。先做分层压测不要直接压业务接口。底层存储用 fio 测网络用 iperf 测CPU用 sysbench 测。这样能确认每一层的基础性能是多少后面出问题才知道是哪层掉了。边压测边采集数据推荐的工具组合mpstat -P ALL 1看每个CPU的利用率、steal和软中断pidstat看进程线程级的CPU消耗iostat -x 1看块设备的%util、await、avgqu-szsar -n DEV 1看网卡PPS和带宽numastat看NUMA访问情况。每一层跑完记录基线数据把“哪个资源先撞到天花板”这个问题以数据形式回答出来再开始想方案。我举个例子。之前有一个项目业务人员反馈数据库虚拟机性能差我上去第一轮压测就发现Guest内部CPU不忙iowait也不高但网络P99波动特别离谱。后来看/proc/interrupts发现所有网络中断全部落在了CPU0上vhost线程还在不同核之间漂移。这个如果不做分层摸底单纯去调CPU绑核根本找不到方向。还有一点采集数据的时候时间线要对齐。不要这分钟看CPU下分钟看网络压力已经变了。我习惯用sar -o把所有数据落盘压测结束后统一回放时间轴这样每个指标之间的因果关系才能串联起来。2. CPU 调优从虚拟核分配到真正“独占CPU”2.1 vCPU 数量与超分比例怎么定虚拟机的vCPU数量不是越多越好。很多人习惯直接给虚拟机开满物理核觉得这样性能最好其实这是一个很大的误区。vCPU在宿主机上本质是一个QEMU线程Guest里的每个CPU指令最终要通过这个线程调度到物理核上执行。vCPU数量给多了会带来几个问题Guest内的锁竞争变多特别是内核的调度器和内存管理QEMU的调度开销增加上下文切换变频繁更麻烦的是宿主机超分之后物理核不足时vCPU会排队延迟直接拉高。超分比的建议我整理过一版比较实用1:1 到 1:2适合对延迟极其敏感的业务需要高QoS保障最好还是参考这个比例来规划。1:3 到 1:6适合一般Web应用、开发测试环境业务本身有弹性偶发等待可以接受。超过 1:8只适合离线计算、批处理任务对延迟不敏感跑慢了也无所谓。怎么确认当前vCPU数量给得合不合理我一般看Guest内的load average和vmstat的r运行队列。如果单核 load 平均长期超过4说明vCPU数量确实不够但如果load不高加了vCPU反而可能出现性能下降因为Guest内核的调度开销大了。关于超分比例我还想补充一个非常容易被忽略的点宿主机的“邻居效应”。就算你的虚拟机只分配了4个vCPU物理机上有其他业务把物理核占满了你的延迟照样拉胯。所以关键业务虚拟机在宿主机上的布局必须和CPU绑核一起考虑不能只看超分数字。2.2 物理核心绑定让虚拟机不再“抢CPU”CPU绑定Pinning是虚拟化性能优化里最立竿见影的操作之一。它的思路很简单把虚拟机的vCPU线程固定到特定的物理核上不让它在宿主机内核的调度器里到处跑。好处有两个一个是避免CPU缓存频繁失效另一个是保证vCPU不会因为宿主机调度被置换出去。在KVM/QEMU环境中我常用两种方式一种是通过libvirt配置在domain XML里写cputune vcpupin vcpu0 cpuset2/ vcpupin vcpu1 cpuset3/ vcpupin vcpu2 cpuset4/ vcpupin vcpu3 cpuset5/ emulatorpin cpuset0/ /cputune另一种是运行时用virsh vcpupin动态指定virsh vcpupin vm_name 0 2不重启虚拟机就能生效。但需要留意的是虚拟机重启之后有些配置可能被覆盖所以正式环境一定要把XML写进配置文件不要只在线设置。绑核时有一个大坑不要绑超线程的逻辑核。现在很多物理机开了超线程一个物理核对应两个逻辑CPU如果你把vCPU绑在同一个物理核的两个逻辑核上它们实际是在抢同一个执行单元看着是两个核实际还是“伪并行”。正确的做法是先查/proc/cpuinfo或者用lscpu -e分清物理核ID和逻辑核ID给每个vCPU分配不同的物理核。如果宿主机上还有其他物理CPU空闲更彻底的做法是在内核启动参数里加上isolcpus把那几个物理核从宿主机调度器中隔离出来专门给关键虚拟机使用。我自己在调某实时风控模拟项目的虚拟机时就是用isolcpus2,3,4,5搭配nohz_full把不必要的中断和调度tick全部从这几个核上摘掉延迟毛刺明显少了很多。2.3 中断与软中断毫秒延迟的隐形杀手很多人的CPU调优止步于vCPU绑核但延迟波动最大的隐患其实在中断处理上。虚拟机的网络包和磁盘I/O中断如果落在某个CPU上就会抢占该CPU正在执行的vCPU线程造成可观测的延迟毛刺。先看中断情况。执行下面命令看每个CPU的中断分布cat /proc/interrupts你会发现某些中断比如 virtio0-input、virtio0-output集中在一个CPU上这个CPU会被打满。这时候需要调整中断亲和性把中断分散到多个核echo 0x3c /proc/irq/中断号/smp_affinity这里0x3c对应的二进制是111100代表CPU2到CPU5具体数值根据你的拓扑来填。另外很多系统默认开着irqbalance它会自动平衡中断到各个CPU看起来很好但它会对延迟敏感业务造成伤害——中断可能在运行过程中被转移到其他核vCPU再绑定也没用。我在优化这类场景时基本都是先把irqbalance关掉systemctl stop irqbalance systemctl disable irqbalance然后手动设置中断亲和性以及RPS/XPS确保网络包分发路径完全可控。这套组合拳做完P99延迟的抖动通常能降低一个数量级。3. 内存调优让虚拟机访存从“绕远路”变成“直达”3.1 大页内存TLB 小了延迟就降了内存这块第一优先考虑的是大页内存HugePages尤其是对内存访问密集的数据库、缓存类业务收益非常明显。先解释一下为什么大页有用。默认情况下Linux内存页大小是4KB虚拟机的每个内存访问都要通过TLB翻译后备缓冲做地址转换。TLB的条目数是有限的如果内存地址对应的页数太多TLB存不下就会触发TLB missCPU需要到内存里去查页表延迟直接上一个量级。把页大小从4KB改成2MB需要的TLB条目少了512倍TLB miss概率大幅下降访存自然就快了。配置大页分两步。第一步是宿主机预留大页内存在启动参数里加hugepagesz1G hugepages16或者运行时写入echo 16 /proc/sys/vm/nr_hugepages第二步是让虚拟机使用大页内存。用libvirt的话在domain XML里加入memoryBacking hugepages/ /memoryBacking更精细的做法是给QEMU加上-object memory-backend-file,size32G,mem-path/dev/hugepages把虚拟机内存放到hugepages挂载点上。这里有个容易踩的坑透明大页THP建议关掉。THP是内核自动把内存页合并成大页听着方便但在长期运行的虚拟机上会导致页表碎片化还时不时触发khugepaged线程扫描合并产生延迟毛刺。我一般会在宿主和Guest里都关掉echo never /sys/kernel/mm/transparent_hugepage/enabled大页配置完成后还要检查一下是否真的生效cat /proc/meminfo看HugePages_Free是否在减少或者看QEMU进程的RSS是否明显低于虚拟机的内存配置。如果配了16个1G大页但虚拟机内存只有4G剩下的大页就白白浪费了所以大页大小要按虚拟机实际内存来预留。3.2 NUMA 感知谁和谁在一起很重要多路服务器的内存不是均匀的每个CPU核访问本地内存和远端内存的延迟差可以达到20%甚至更多。虚拟化层如果没做好NUMA亲和虚拟机一会被调度到Node 0一会被调度到Node 1内存也在两个Node上乱散性能会忽高忽低。先看宿主机的NUMA拓扑numactl --hardware numastat然后给关键虚拟机设置NUMA策略。用libvirt可以这样virsh numatune vm_name --mode strict --nodeset 0如果虚拟机比较大跨了多个NUMA节点那就要保证虚拟机的vCPU分布和内存分布是绑定的同一个Node。QEMU启动参数一般是-m 32G \ -object memory-backend-ram,size16G,idm0,host-nodes0,policybind \ -object memory-backend-ram,size16G,idm1,host-nodes1,policybind \ -numa node,nodeid0,cpus0-3,memdevm0 \ -numa node,nodeid1,cpus4-7,memdevm1这样一组一组显式绑定确保Guest内跑的线程和它访问的内存在同一个物理节点上。我之前调优那次一开始没做NUMA感知结果发现P99隔一段时间就跳一次查了半天发现QEMU把虚拟机的内存在两个NUMA节点上各分了一半而所有vCPU又都被调度到其中一个节点上等于一半的内存在跨节点访问。做了NUMA绑定之后这个问题直接消失延迟曲线变得非常干净。3.3 内存回收与swap陷阱别让虚拟化层替业务背锅Guest内的swap是性能杀手这点大家都懂但容易被忽视的是宿主机和QEMU层面的一些内存回收机制。先看swappiness。默认值是60对虚拟机来说太高了它会让Guest内核倾向于把不常用内存页换到swap而不是优先回收page cache。建议在Guest内设为10以下sysctl -w vm.swappiness10再注意内存气球balloon。这是虚拟化层用来回收Guest空闲内存的机制但在有些场景下会自动踩油门把Guest内存压缩得很紧导致Guest频繁进行内存回收表现为延迟飙升。如果业务本身对内存有严格要求建议把balloon直接禁用掉virsh domblklist vm_name # 查看有无 balloon 设备配置中直接移除最后检查一下Guest内是不是有kswapd、kcompactd在频繁运行如果有说明Guest内存压力大。但别急着提业务内存先看宿主机node上是不是内存不够了或者大页预留太多了把普通内存挤占干净了。很多时候问题不在Guest而在宿主的内存分配策略。4. 磁盘 I/O 调优从虚拟队列到硬件加速4.1 virtio 半虚拟化为什么是默认首选磁盘I/O是另一个性能重灾区。如果你的虚拟机还在用IDE或者SATA控制器模拟性能基本就是“老牛拉车”因为每个I/O请求都要经过复杂的设备模拟路径。virtio半虚拟化通过共享内存队列让Guest直接与宿主通信大幅减少模拟开销这也是一般云平台默认选型的原因。在virtio的细分选择上我建议普通应用选择virtio-blk就行配置简单性能稳定。如果虚拟机需要挂载很多块云盘或者需要动态扩展用virtio-scsi更灵活支持多设备队列。如果是数据库场景且对延迟极致敏感在允许条件下可以考虑PCIe NVMe直通让虚拟机直接访问物理SSD。但直通会失去热迁移等虚拟化特性运维复杂度上升一般虚拟机环境我不建议一开始就上。4.2 iothread 与队列深度榨干每一条 I/O 通道默认情况下虚拟机的I/O处理会占用vCPU线程。也就是说Guest发一个I/O请求vCPU会被卡住等待I/O完成这期间其他计算任务也在等。解决思路是配置iothread把I/O处理从vCPU线程中独立出来。libvirt下配置iothread并在磁盘上指定使用iothreads2/iothreads ... disk typefile devicedisk driver nameqemu typeraw cachewriteback iothread1/ source file/data/vm/disk.raw/ target devvda busvirtio/ /diskiothread的核要和vCPU核错开。比如vCPU0-3绑在物理核2-5iothread就绑到物理核0-1用virsh iothreadpin来操作virsh iothreadpin vm_name 1 0队列深度也很重要。virtio-blk默认的队列数量有限I/O压力大的时候会在队列里堆积。可以给QEMU加-device virtio-blk-pci,scsioff,iothread1,num-queues4结合Guest内多队列配置让I/O分散到多个vCPU处理。实测下来IOPS和延迟都能明显改善。关于cache模式的选择我多说两句。writeback模式性能最好但异常断电时可能丢数据比较适合上层有主从复制或者备份保障的数据库场景writethrough安全性高性能略差适合文件服务。none模式相当于绕过QEMU的page cache直接走宿主缓存适合需要应用自己控制缓存的场景。我个人的选择逻辑是先问业务能不能接受断电丢几秒数据能就writeback不能就writethrough不要盲目追求最快的cache模式。4.3 磁盘I/O压测与常见问题I/O调优有没有效果不能只看感觉要拿数据说话。我用 fio 做一轮4K随机读写的压测典型命令fio --nametest --rwrandread --bs4k --size8G --iodepth32 --numjobs4 --direct1压测时配合iostat -x 1观察每块盘的IOPS、await平均I/O延迟和avgqu-sz平均队列长度。如果await上去了、util也满了多半是存储侧能力打满如果await不高但业务还是慢那就要去看客户端的锁竞争和软件栈。我还碰到过一个印象很深的场景虚拟机映像文件是qcow2而且叠了一层快照性能衰减非常明显。qcow2本身有元数据查找的开销加上快照会造成写时复制COW性能直接腰斩。后来我把镜像从qcow2转成raw并且用fallocate预分配空间延迟毛刺立刻消失。所以性能敏感的业务虚拟机镜像格式能选raw就尽量选raw快照层数越少越好。这里再提醒一个细节如果QEMU用了raw格式的块设备而后端是普通文件那page cache会被双层缓存Guest一层、宿主一层。对数据库这类有自己Buffer Pool的业务可以考虑把缓存模式设为none避免双缓存带来的内存浪费和不稳定。5. 网络调优让数据包不再“路过”太多层5.1 多队列 virtio-net 与 RPS/XPS网络延迟是毫秒级业务最敏感的环节。虚拟机的网络包路径比物理机长得多数据到宿主机网卡进内核协议栈经过virtio队列由vhost处理再通知到Guest的驱动中间任何一个环节阻塞延迟都会爆炸。默认的virtio-net只有单队列所有收包都挤在一个中断上一个CPU处理不过来。开启多队列可以按队列分发到不同vCPUlibvirt里的配置interface typebridge source bridgebr0/ model typevirtio/ driver namevhost queues4/ /interfaceGuest内再把网卡队列数设为4ethtool -L eth0 combined 4开启多队列后还要配合RPSReceive Packet Steering和XPSTransmit Packet Steering让软中断分散到不同核。话句话说如果只开队列不绑核那4个队列仍然可能由一个CPU处理负载不均衡的问题依旧存在。RPS配置示例echo fc /sys/class/net/eth0/queues/rx-0/rps_cpus这里的fc是一个CPU位图具体值根据你要使用的CPU编号算出来。5.2 vhost 线程与 CPU 亲和处理包的人不能中途换班在KVM环境里网络数据包的处理线程是vhost。vhost不是Guest进程而是宿主内核里处理virtio队列的线程。如果vhost线程不绑CPU它可能在宿主机的多个核之间漂移缓存和中断亲和性都会失效P99抖动特别明显。先找到vhost线程ps -eLf | grep vhost然后绑定CPUtaskset -p 0x3c vhost_pid绑完再检查/proc/interrupts确保对应的virtio中断也落在同一批CPU上。我一般把vhost线程和Guest的网卡多队列绑在同一个物理核组这样收包路径上所有处理环节都是本地缓存命中延迟最低。如果业务量巨大对单虚机吞吐要求很高还可以考虑vhost-user加上DPDK的方案让数据包在用户态直接处理。但这个东西复杂度非常高牵扯内存大页、CPU隔离、专用驱动一堆配置一般生产环境没到那个量级我建议先把vhost绑核做好再说。5.3 网络常见误区与实测案例网络调优的坑特别多我遇到过的典型反例就有好几个。第一个误区是只开多队列不绑核不开RPS。有一次我压测某业务QPS死活上不去上去一看四个网卡队列全部由CPU0一个核处理软中断占比百分百其他核闲得发慌。这种情况多队列等于白开。第二个误区是中断亲和性与vhost绑核不一致。/proc/interrupts显示中断落在CPU2、CPU3vhost线程却绑在CPU6数据包从网卡中断到vhost再到Guest路径是跨核的延迟表现不如人意。调优时要把中断、vhost、vCPU三者调度到同一个物理核组性能才会稳定。第三个误区是盲目上DPDK忽视了标准方案。有一次压测网络正常调优后QPS已经达到需求业务方还是觉得要上DPDK结果引入一堆内存、端口配置问题最后回退到virtio多队列vhost绑核稳定性和延迟反而更好。高延迟问题多数情况下不是设备层面的而是路径上的调度不公平先把基础优化做完再说。我实测的一个对比数据某模拟网关业务调优前QPS约3.2万P99延迟8.5ms关闭irqbalance、开启四队列、vhost绑核之后QPS提升到4.8万P99延迟降到2.1ms。这个改善非常显著而所有操作都不涉及硬件更换。6. 从瓶颈到毫秒级响应一次完整调优实战复盘6.1 场景与初始压测结果讲这么多理论最后用一个真实的调优案例把整个流程串起来。某模拟支付网关业务部署在一台8 vCPU、32G内存的虚拟机上宿主是2路物理服务器跑着若干台虚拟机。业务压测时接口P99延迟48ms高峰期QPS只有3000左右业务方一度怀疑是SQL问题但检查后没有慢查询锁等待也很少于是把问题抛到虚拟化这里。我先做分层摸底结果如下CPUGuest内整体负载不高但宿主机%steal高达12%说明物理核重叠严重。内存numastat显示内存跨Node分配Guest内的页表访问有跨节点现象。磁盘fio 4K随机读延迟1.5msiowait约20%不高不低但镜像文件是qcow2且带一层快照。网络软中断集中在CPU0vhost线程漂移严重多队列是开启状态但没有绑核。问题已经比较清楚了不是某一个资源瘫痪而是每一层都有一定开销累积起来延迟就被拉到一个无法接受的水平。6.2 逐层调整与前后对比我的原则是每次只改一层改完立刻压测避免多个变量混淆。整个调优过程分四轮执行下面这张表记录了每一轮的动作和效果。轮次调整内容P99延迟峰值QPS%steal备注基线无48ms300012%抖动明显第一轮vCPU绑核关闭irqbalance32ms34006%延迟下降但仍有毛刺第二轮大页内存NUMA strict绑定18ms38005%CPU竞争缓解访存稳定第三轮iothread隔离磁盘镜像转raw并预分配9ms41004%磁盘路径通畅第四轮网卡四队列vhost绑核中断亲和2.8ms49003%网络路径稳定逐层调整的规律很明显每一层的优化都在减小排队和等待但单独拿出来都不会有“奇迹”最终毫秒级响应是综合结果。如果把顺序反过来先做网络后做磁盘可能第一轮效果没那么明显容易导致误判优先级。第四轮做完P99延迟从48ms降到2.8msQPS从3000提升到4900业务侧的毛刺也基本消失了。整个调优过程没有更换任何硬件也没有动应用代码纯粹靠虚拟化层和宿主机调度优化打到了这个水平。6.3 如何一直保持毫秒级响应状态调优完不是终点保持状态才是难点。虚拟化环境最怕“时间一长配置被静默破坏”比如某个维护窗口期间重启了宿主机isolcpus参数忘了加或者系统更新后irqbalance服务又自动启动更烦人的是其他VM的突发流量导致CPU steal时间重新上升。我的建议是建立三件事配置模版化把最优配置写进libvirt或云平台的规格模板里每次创建虚拟机自动带上新虚拟机不会走一遍弯路。基线巡检每周或每两周跑一轮标准化压测记录P99、QPS、%steal、iowait等关键指标与基线对比。超过阈值就报警避免问题积累到不可收拾才发现。容量预留关键业务所在宿主机不要做满负荷部署CPU超分比例控制好至少留出20%的物理核余量应付突发行情和邻居VM干扰。另外还有一个容易被忽略的点业务流量模型的长期变化。调优时基于当时的并发模型选了4个网卡队列、2个iothread半年后业务量翻倍队列数和绑核策略可能需要重新评估。所以调优文档不是一次性的每个季度应该回头审视一遍。我个人在实际操作中的体会是虚拟机性能优化最怕“一把梭”上来就上各种高级特性比如SR-IOV直通、DPDK不仅复杂度高而且很难回退。真正成熟的优化一定是先做基础层的绑核、大页、iothread、多队列这些做扎实了大部分场景都能达到满意效果。整个过程里每次只改一个变量、每次改动都能用数据验证效果是最高效也最稳妥的路径。最后再分享一个小技巧被延迟毛刺折磨的时候优先查/proc/interrupts和宿主机的%steal这两个指标能直接告诉你虚拟机是不是在物理资源上“排队”解决好这两件事性能优化就成功了一半。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询