# 网卡中断亲和性怎么配 多核CPU网络性能调优
服务器CPU跑不满、网络吞吐量上不去,很多时候不是网卡性能不够,而是中断全挤在一个CPU核上。这个问题在10G/25G环境下尤其明显——单核处理中断的能力有上限,一旦瓶颈形成,再多带宽也白搭。本文从决策维度出发,帮你快速定位该怎么配、配给谁。
网卡每收到一个数据包,就向CPU发一个硬件中断(IRQ)。默认情况下,Linux把所有网卡中断交给CPU0处理。8核服务器跑1G流量无所谓,但10G线速场景下每秒数百万个包,CPU0被打满,其他核心空转——这就是中断亲和性要解决的问题。
中断亲和性(IRQ Affinity)是指把特定硬件中断绑定到指定CPU核心的机制。通过/proc/irq/{irq_num}/smp_affinity可以控制每个中断由哪些核心响应。配合网卡的多队列(Multi-Queue / RSS)能力,把不同队列的中断分散到不同核心,才能把多核CPU的算力真正用起来。
RSS(Receive Side Scaling)是网卡硬件级的多队列分流技术。网卡根据数据包的哈希值(通常取源IP+目的IP+源端口+目的端口)把流量分配到多个接收队列,每个队列对应一个独立中断,从而实现多核并行处理。
配置中断亲和性的第一步是搞清楚你的网卡支持多少个接收/发送队列,以及服务器有几个物理核心。两者取较小值,就是你实际能并行处理中断的上限。
| 型号 | 接口 | 速率 | PCIe | 功耗 | 多队列支持 |
|---|---|---|---|---|---|
| LRES1027PF-4SFP28 | 4×SFP28 | 25G | 4.0 x8 | 22.0W | RSS多队列,DPDK |
| LREC9804BF-4SFP+ | 4×SFP+ | 10G | 3.0 x8 | 7.4W | RSS多队列,DPDK |
| LREC9812BT | 2×RJ45 | 10G | x4 | 11.2W | RSS多队列 |
四口25G网卡在高吞吐场景下每个端口都能独立产生中断流,配合RSS多队列可以充分利用多核CPU。对于需要RDMA的数据中心场景,这款网卡同时支持iWARP和RoCE v2。
四口10G SFP+方案功耗只有7.4W,四端口共享PCIe 3.0 x8带宽。适合需要多路10G光纤接入但预算和功耗都有限的场景。
双口10G RJ45方案走铜缆布线,适合机房内短距离10G互联。PCIe x4接口对主板槽位要求低,半高挡板兼容1U/2U服务器。
10G线速小包场景每秒约1488万个包,单核处理能力约100万中断/秒,理论上至少需要16个核才能扛住。25G更是翻倍。这就是为什么多队列+中断分散不是锦上添花,而是必需。
Linux自带irqbalance守护进程,自动在所有CPU核心之间分配中断。大多数桌面和轻负载服务器开着它就行。但在高吞吐网络场景下,irqbalance的自动调度有两个问题:
- NUMA感知不足:irqbalance可能把网卡中断分配到远端NUMA节点的核心上,跨NUMA访问内存延迟增加约30-50%
- 频繁迁移:自动调度会在核心之间迁移中断处理,导致CPU缓存命中率下降
当服务器跑10G/25G线速流量,且CPU有NUMA多节点时,建议关闭irqbalance,手动做中断绑定。低负载或单路CPU的服务器保持irqbalance开启即可。
根据你的网卡类型、CPU架构和流量特征,快速找到对应的配置方案:
| 场景 | 网卡类型 | CPU架构 | 推荐策略 | 关键操作 |
|------|---------|---------|---------|---------|
| 轻负载办公服务器 | 单口千兆 | 单路4-8核 | irqbalance默认 | 无需额外配置 |
| 中等负载Web/数据库 | 双口10G RJ45 | 单路8-16核 | irqbalance + RSS | 确认RSS队列开启 |
| 高吞吐存储/虚拟化 | 四口10G SFP+ | 双路16-32核 | 手动绑定 + NUMA对齐 | 关irqbalance,绑核 |
| 25G数据中心 | 四口25G SFP28 | 双路32-64核 | 手动绑定 + NUMA + RPS | 全手动精细调优 |
10G以上线速环境,关掉irqbalance做手动中断绑定是基本操作。网卡队列数要和绑定的CPU核数对齐,同时确保中断绑在网卡所在的NUMA节点上。
查看网卡中断号:
# 找到网卡接口名对应的中断号
cat /proc/interrupts | grep eth
# 或者用更精确的方式
grep -i eth /proc/interrupts | awk '{print $1}' | tr -d ':'
查看每个中断的当前亲和性掩码:
# 查看所有IRQ的CPU亲和性
for irq in $(ls /proc/irq/ | grep -E '^[0-9]+$'); do
affinity=$(cat /proc/irq/$irq/smp_affinity 2>/dev/null)
if [ -n "$affinity" ]; then
echo "IRQ $irq: $affinity"
fi
done
手动绑定中断到指定CPU核心:
# 关闭irqbalance
systemctl stop irqbalance
systemctl disable irqbalance
# 假设网卡有4个RX队列,对应中断号为 50 51 52 53
# 分别绑定到CPU 0 1 2 3(掩码:1=CPU0, 2=CPU1, 4=CPU2, 8=CPU3)
echo 1 > /proc/irq/50/smp_affinity
echo 2 > /proc/irq/51/smp_affinity
echo 4 > /proc/irq/52/smp_affinity
echo 8 > /proc/irq/53/smp_affinity
# 验证绑定结果
cat /proc/irq/50/smp_affinity_list
cat /proc/irq/51/smp_affinity_list
掩码是十六进制位图。0x1=CPU0, 0x2=CPU1, 0x4=CPU2, 0x8=CPU3, 0xf=CPU0-3, 0xff=CPU0-7。也可以用smp_affinity_list写十进制核号,如echo 0 > /proc/irq/50/smp_affinity_list表示绑到CPU0。
NUMA感知的中断绑定脚本(双路服务器):
# 查看网卡所在NUMA节点
cat /sys/class/net/eth0/device/numa_node
# 查看每个CPU属于哪个NUMA节点
lscpu | grep NUMA
# 把网卡中断绑到网卡所在NUMA节点的核心上
# 假设网卡在NUMA node 0,node 0包含CPU 0-15
for irq in $(grep eth0 /proc/interrupts | awk '{print $1}' | tr -d ':'); do
echo 0-15 > /proc/irq/$irq/smp_affinity_list
done
多队列网卡需要确认RSS已启用并正确配置队列数:
# 查看当前RSS队列数
ethtool -l eth0
# 设置RSS队列数(与绑定CPU核数对齐)
ethtool -L eth0 combined 4
# 查看RSS哈希配置
ethtool -n eth0 rx-flow-hash tcp4
ethtool -n eth0 rx-flow-hash udp4
# 优化RSS哈希:加入端口号参与计算(默认可能只算IP)
ethtool -N eth0 rx-flow-hash tcp4 sdfn
ethtool -N eth0 rx-flow-hash udp4 sdfn
配置完成后用 cat /proc/interrupts 观察各CPU的中断计数是否均匀增长,用 mpstat -P ALL 1 观察各核利用率是否平衡。优化后单核瓶颈消除,吞吐量通常提升2-4倍。
虚拟机环境:VMware ESXi和KVM的中断处理机制不同。KVM下直通(passthrough)网卡的中断绑定在宿主机层面配置;virtio网卡的中断由虚拟CPU处理,需要在虚拟机内部做绑定。
DPDK场景:如果使用DPDK做用户态收包,内核中断亲和性配置不再生效。DPDK通过PMD(Poll Mode Driver)轮询收包,中断被完全绕过。LRES1027PF-4SFP28和LREC9804BF-4SFP+均支持DPDK。
CPU核数远大于队列数:比如64核CPU配4队列网卡,不能每个核绑一个队列。这时把中断集中绑到少数核心上,剩余核心专门跑应用进程,通过taskset或cgroup隔离。
超线程的影响:超线程让一个物理核模拟出两个逻辑核。中断绑定建议绑到物理核的第一个逻辑核上(通常偶数编号),避免同一物理核的两个逻辑核争抢L1/L2缓存。
- 1G环境、8核以下:开irqbalance,不折腾
- 10G、单路CPU:开irqbalance + 确认RSS队列数 ≥ 4
- 10G、双路NUMA:关irqbalance,手动绑核,NUMA对齐
- 25G、双路NUMA:全手动,NUMA对齐,RSS哈希优化,考虑DPDK
技术调优的目标不是追求某个参数最大化,而是消除瓶颈让系统各组件均衡运转。
用 ethtool -l eth0 查看,输出中"Combined"列的"Current"值就是当前启用的队列数。不同网卡支持的最大队列数不同,四口25G网卡通常支持到16-64个队列。如果显示只有1个队列,说明RSS没有被驱动正确启用,需要检查驱动版本。
两者功能一样,只是写法不同。smp_affinity用十六进制掩码(如0x0f表示CPU0-3),smp_affinity_list用十进制核号(如0-3或0,2,4)。日常用smp_affinity_list更直观,不容易算错位。
如果只是systemctl stop irqbalance,重启后irqbalance会重新启用。需要同时执行systemctl disable irqbalance禁止开机自启。建议把中断绑定脚本写进/etc/rc.local或systemd service,确保开机自动生效。
三个常见原因:RSS队列数没和绑定核数对齐(比如绑了4个核但RSS只有1个队列);流量特征太单一导致RSS哈希分布不均(所有包算出相同哈希值进同一队列);网卡本身不支持多队列。先用ethtool -S eth0看每个队列的实际收包数,确认分流是否生效。