彻底解决 si 满载:高并发下 Linux 多队列网卡 RSS 性能调优实战
在高并发的互联网应用中,我们经常会遇到这样一种尴尬的情况:服务器 CPU 整体占用率并不高,但其中的某一个核心(通常是 CPU0)的 si(Softirq,软中断)字段长时间处于 80%-100% 之间。伴随而来的是网络响应延迟抖动、吞吐量上不去,甚至出现严重的丢包现象。
这是典型的网卡软中断不均导致的单核瓶颈。本文将深入探讨如何通过多队列网卡与 RSS(Receive Side Scaling)技术,将网络处理压力从单核释放到多核。
一、 现象定位:如何确定是软中断瓶颈?
首先,通过 top 命令进入交互界面,按 1 查看每个逻辑 CPU 的详细指标。如果发现某个核心的 si 占比远高于其他核心,说明软中断处理出现了倾斜。
接着,我们可以通过以下命令实时观察网卡中断在各 CPU 上的分布情况:
watch -d -n 1 "cat /proc/interrupts | grep -E 'eth0|em1|pci'"
如果发现只有少数几个中断号在频繁计数,且对应的 CPU 编号非常固定,说明网卡的多队列特性未被充分利用或配置错误。
二、 核心武器:RSS(Receive Side Scaling)
RSS 是网卡层面的硬件负载均衡技术。它通过对数据包(通常是五元组:源IP、目的IP、源端口、目的端口、协议)进行哈希运算,将流量分配到网卡的不同硬件接收队列中。
1. 检查网卡是否支持多队列
使用 ethtool 工具检查当前网卡的队列能力:
# 假设网卡名为 eth0
ethtool -l eth0
输出示例:
Channel parameters for eth0:
Pre-set maximums:
RX: 0
TX: 0
Other: 0
Combined: 8 # 硬件支持的最大队列数为 8
Current hardware settings:
RX: 0
TX: 0
Other: 0
Combined: 1 # 当前仅启用了 1 个队列
如果 Combined 的当前值小于最大值,说明性能被白白浪费了。
2. 开启多队列
将队列数调整为与 CPU 核心数一致(或符合 NUMA 架构的物理核数):
ethtool -L eth0 combined 8
三、 进阶调优:手动绑定中断亲和性(IRQ Affinity)
虽然开启了多队列,但如果内核的 irqbalance 服务配置不当,中断依然可能聚集在少数核心。在高并发场景下,我们通常建议关闭 irqbalance,并进行手动绑核。
1. 关闭 irqbalance
systemctl stop irqbalance
systemctl disable irqbalance
2. 获取队列的中断号
查出每个队列对应的中断号(IRQ Number):
grep "eth0-fp" /proc/interrupts | awk '{print $1}' | sed 's/://'
3. 设置亲和性掩码
对于每一个中断号,将其对应的 CPU 掩码写入 /proc/irq/{IRQ_ID}/smp_affinity。
例如,若想让 IRQ 120 跑在 CPU 0 上,掩码为 1;跑在 CPU 1 上,掩码为 2;跑在 CPU 2 上,掩码为 4。
实战脚本片段(自动分配):
# 简单的绑定逻辑:将 eth0 的第 n 个中断绑定到第 n 个 CPU 核心
MAX_CORES=$(nproc)
QUEUES=$(grep "eth0" /proc/interrupts | awk '{print $1}' | sed 's/://')
CORE=0
for IRQ in $QUEUES; do
MASK=$(printf "%x" $((1 << CORE)))
echo $MASK > /proc/irq/$IRQ/smp_affinity
echo "Assigning IRQ $IRQ to CPU $CORE with mask $MASK"
CORE=$(( (CORE + 1) % MAX_CORES ))
done
四、 如果硬件不支持多队列怎么办?(RPS 技术)
如果你的服务器运行在虚拟机上,或者网卡本身不支持多队列(RSS),那么可以使用 Linux 内核提供的软件模拟方案:RPS (Receive Packet Steering)。
RPS 在内核驱动层拦截数据包,并通过哈希分发到不同的 CPU 积压队列(Backlog Queue)中处理。
开启方法:
将希望参与处理的 CPU 掩码写入对应的队列文件:
# 假设是单队列网卡,对所有 CPU 开启 RPS (以 8 核为例,掩码 ff)
echo "ff" > /sys/class/net/eth0/queues/rx-0/rps_cpus
五、 注意事项与最佳实践
- NUMA 亲和性:在双路 CPU 服务器上,务必将网卡中断绑定到网卡物理插槽所属的那个 CPU Node 上。跨 Node 访问内存会带来巨大的 QPI 总线开销,抵消优化效果。
- 避免 CPU0 陷阱:系统时钟中断、控制台 I/O 等默认都压在 CPU0 上,尽量让网卡中断从 CPU1 开始分配。
- 监控工具:推荐使用
netstat -i配合mpstat -P ALL 1来验证调整后的效果,观察软中断是否均匀分布在各个核心。
总结
在高并发环境下,单核处理软中断的模式已经成为历史。通过 RSS 硬件多队列 + 手动 IRQ 亲和性绑定,我们可以将网络处理能力线性扩展到多核。这不仅能显著降低单核 si 占用,还能大幅提升系统的并发吞吐能力。如果你的系统正遭受网络瓶颈困扰,不妨从 ethtool -l 开始你的排查之旅。