irqbalance默认POWERSAVING策略会将网卡中断聚合到少数CPU以省电,导致softirq集中打满单核;应停用irqbalance,按物理核和NUMA节点手动绑定各队列IRQ,并关闭RPS/RFS。

为什么 irqbalance 默认策略会让网卡中断集中到单个 CPU?
irqbalance 默认使用 POWERSAVING 模式(尤其在低负载时),会主动将中断聚合到少数 CPU 上以降低功耗。网卡多队列(如 eth0-TxRx-0 到 eth0-TxRx-7)的 IRQ 如果被合并调度到同一物理核,该核的 softirq(特别是 NET_RX)就会持续打满,而其他核空闲。
这不是 bug,是设计取舍——但对高吞吐、低延迟网络场景完全不适用。
- 确认当前模式:
irqbalance --debug --oneshot 2>&1 | grep "policy" - 查看各 IRQ 实际绑定:
cat /proc/interrupts | grep eth0,观察列中数字是否集中在某几列 - 检查 CPU topology:用
lscpu确认物理核/超线程关系,避免把多个队列绑到同一物理核的两个逻辑 CPU 上
停用 irqbalance 改用手动 IRQ 绑定更可控
自动均衡器在 NUMA 多插槽、异构核心(如 Intel P/E 核)、或启用了 isolcpus 的场景下极易误判。直接关闭它,用 set_irq_affinity.sh(内核自带)或手动写 /proc/irq/*/smp_affinity_list 更可靠。
- 停服务:
systemctl stop irqbalance && systemctl disable irqbalance - 查网卡支持队列数:
ethtool -l eth0 | grep "Current hardware settings" - 运行绑定脚本:
/usr/lib/irqbalance/set_irq_affinity.sh eth0(注意:该脚本默认按物理核轮询,但需确认其行为是否匹配你的拓扑) - 若脚本不适用,手动绑定示例:
echo 0-1,4-5 > /proc/irq/123/smp_affinity_list(其中 123 是对应队列 IRQ 号)
绑定时必须避开超线程同核干扰和 NUMA 跨节点访问
把 eth0-TxRx-0 和 eth0-TxRx-1 都绑到 CPU0 和 CPU1(即同一物理核的两个逻辑 CPU),会导致 L1/L2 缓存争抢,softirq 处理延迟反而升高。同样,若网卡在 Node 0,却把中断绑到 Node 1 的 CPU,会触发跨 NUMA 访存,带宽下降明显。
- 用
lscpu和numactl --hardware明确每个 CPU 所属 Node 和 Core ID - 优先将每个队列绑定到不同物理核的第一个逻辑 CPU(如 CPU0、CPU2、CPU4…)
- 确认网卡所在 NUMA node:
lspci -vv -s $(ethtool -i eth0 | grep bus-info | awk '{print $2}') | grep NUMA - 绑定后验证:运行
watch -n1 'cat /proc/interrupts | grep eth0',观察各列计数是否均匀增长
softirq 打满还可能和 RPS/RFS 配置冲突
即使 IRQ 分散了,如果启用了 RPS(Receive Packet Steering)且配置不当,仍可能让所有软中断集中在某个 CPU 处理。RPS 是在 softirq 上层做二次分发,和底层 IRQ 绑定是两层机制,容易叠加错位。
- 检查是否启用:
cat /sys/class/net/eth0/queues/rx-0/rps_cpus,非全 0 表示启用 - 高吞吐场景建议关闭 RPS:
echo 0 > /sys/class/net/eth0/queues/rx-0/rps_cpus(全部 rx 队列都要关) - RFS(RPS 的流感知增强版)更要禁用,它依赖
net.core.rps_sock_flow_entries,易引发 hash 冲突和单核热点 - 确认无残留:
sysctl net.core.rps_sock_flow_entries应为 0
真正起效的永远是 IRQ 到物理核的硬绑定;RPS/RFS 在现代多队列网卡上已非必需,反而增加不可控路径。










