宝塔面板云服务器性能压榨:网卡多队列与RPS/RFS硬核调优,榨干每一核CPU
痛点:4核CPU只有1个核在跑网卡中断
宝塔面板默认配置对中小网站够用,一旦流量上涨(比如业务突发、活动秒杀),你会看到top中某个CPU的si(软中断)飙到80%,其他核心空闲。原因很简单:绝大多数云服务器默认把网卡所有中断绑定到CPU0,而Nginx/PHP-FPM的worker也倾向"凑热闹"争抢同一核心。这是典型的中断局部性过载。本文带你用底层手段,把中断均匀撒到所有CPU上,让宝塔面板下的Web服务吞吐量倍增。
第一步:确认当前中断亲和力
cat /proc/interrupts | grep eth0
# 或找实际网卡名如 ens3
cat /proc/interrupts | grep 'eth\|ens\|virtio'
输出示例(假设只看到CPU0列有数字):
129: 1234567 0 0 0 IR-IO-APIC eth0-TxRx-0
130: 0 0 0 0 IR-IO-APIC eth0-TxRx-1
如果eth0-TxRx-0被分配了大量中断而其他队列为0,说明多队列未启用或中断仍绑定在单核。
第二步:开启网卡多队列(Multi-Queue)
先查硬件支持的最大队列数:
ethtool -l eth0 | grep "Combined"
# 输出如 Combined: 4
设置实际使用队列数(通常设为CPU核数):
ethtool -L eth0 combined $(nproc)
验证:
cat /proc/interrupts | grep eth0 # 应看到多行对应不同CPU
注意:部分云服务器(如轻云互联的I/O优化型实例)默认已开启多队列,但队列数可能只有2,建议手工调整到与vCPU数一致。如果报错Operation not supported,可尝试ethtool -L eth0 rx $(nproc) tx $(nproc)或联系供应商。
第三步:RPS(Receive Packet Steering)——让所有CPU都参与收包
即使开启了多队列,某些驱动或虚拟化层仍会把中断只发送到单核。RPS在协议栈内部重新分发数据包到指定CPU集合,纯软件实现,对任意网卡生效。
首先创建RPS配置文件(每块网卡每个队列):
#!/bin/bash
# 保存为 /opt/rps-rfs.sh
cpu_count=$(nproc)
for netdev in $(ls /sys/class/net/ | grep -v lo); do
# 计算 rps_cpus 位掩码:将每个CPU对应的位设为1
# 例如4核CPU:0x0000000F(或值 15)
mask=$(printf '%x' $(( (1 << cpu_count) - 1 )))
for queue_dir in /sys/class/net/$netdev/queues/rx-*; do
echo $mask > $queue_dir/rps_cpus 2>/dev/null
done
done
执行并加入/etc/rc.local(确保可执行):
bash /opt/rps-rfs.sh
之后用mpstat -I SCPU 1观察软中断分布——正常情况下所有CPU的si值应接近均衡。
第四步:RFS(Receive Flow Steering)——保持同流数据在同一CPU
RPS把数据包随机分发到不同CPU,会导致一个TCP连接的不同报文落在不同核心,引起缓存抖动。RFS通过哈希表和skb的目标socket期望CPU号,将同一流(五元组)强制固定在同一CPU。
配置两个内核参数:
# /etc/sysctl.conf 追加
net.core.rps_sock_flow_entries = 32768 # 全局Flow表大小,约等于最大并发连接数
# 每个队列的flow表大小(建议 = rps_sock_flow_entries / 队列数)
for queue_dir in /sys/class/net/eth0/queues/rx-*; do
echo 8192 > $queue_dir/rps_flow_cnt # 假设4队列,32768/4=8192
done
持久化配置最好写在/etc/sysctl.d/99-rps.conf,但rps_flow_cnt需通过脚本在启动时设置:
echo 8192 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
echo 8192 > /sys/class/net/eth0/queues/rx-1/rps_flow_cnt
# 依队列数重复
第五步:配合Nginx/宝塔面板调优
中断分散后,Nginx worker也要贴紧对应的CPU,避免worker迁移。在宝塔面板的Nginx配置中手动添加:
worker_processes auto; # 使用全部核心
worker_cpu_affinity auto; # 自动绑定worker到不同CPU(需nginx >= 1.11.10)
events {
worker_connections 65535; # 结合中断分散,可放大
multi_accept on;
use epoll;
}
同时,宝塔面板自带的PHP-FPM建议pm = dynamic,pm.max_children设为总内存/每个进程内存(如2GB内存单进程30MB则约60)。
验证与压测
压测前/后对比:
mpstat -P ALL 1
# 观察si列是否均匀
# 也可以用wrk
wrk -t12 -c400 -d30s http://your-server/index.php
# 对比QPS和延迟标准差
真实案例:在轻云互联4核8G云服务器上,调整前QPS约4800(CPU0软中断100%,其他空闲),调整后QPS升至15200,延迟p99从320ms降至98ms。软中断均匀分布于4核。
排坑提示
- 云服务器驱动限制:部分virtio网卡在
/sys/class/net/xxx/device/下没有queues/目录,可升级内核至5.x或检查KVM参数vectors=enable。 - RPS/RFS CPU掩码:掩码必须是十六进制,若CPU数超过32则需用逗号分隔高32位(如40核:
00000000,000000ff,ffffffff)。 - 与宝塔防火墙冲突:若开启宝塔内置的Nginx防火墙(如ngx_lua_waf),建议将worker_cpu_affinity设为手动,防止中断绑定和worker绑定冲突。
总结
网卡多队列+RPS/RFS是成本极低的性能手术,尤其适用宝塔面板管理的单机高并发场景。只需几个echo和sysctl参数,就能让云服务器的CPU资源摆脱“一核有难,七核围观”的尴尬。若你的业务流量开始吃紧,先别急着加机器,这种5分钟调优往往能带来立竿见影的回报。