net_rx软中断单核过载本质是RSS配置不当导致流量集中,需通过/proc/softirqs和mpstat定位热点CPU,再用ethtool与smp_affinity_list检查并均衡网卡队列中断绑定,辅以GRO关闭、netdev_budget调优及RPS启用。

net_rx 软中断占比过高、导致某个 CPU 核心 100% 占用,本质是内核在该核上持续处理网络数据包收包软中断(NET_RX_SOFTIRQ),来不及返回调度,其他任务被饿死。关键不是“软中断多”,而是“单核集中处理”和“处理不过来”。定位要分三步:确认现象、锁定瓶颈点、验证优化效果。
确认是否真是 net_rx 软中断压满单核
别只看 top 或 htop 的 cpu 使用率——它们把软中断(si)和硬中断(hi)混在 system(sy)里,容易误判。用下面命令看真实分布:
- cat /proc/softirqs:重点关注 NET_RX 行,对比各 CPU 列数值。若某列远高于其他(比如 cpu0 是 cpu1 的 5 倍以上),说明流量集中在该核
- mpstat -P ALL 1:观察每秒的 %soft 字段,确认是否某核 %soft 持续 >90%
- cat /proc/interrupts | grep -i eth:检查硬中断(如 eth0-TxRx-0)是否也集中在同一核——软中断常由同核硬中断触发,二者绑定过紧会雪上加霜
检查网卡中断亲和性与 RSS 配置
现代多队列网卡(如 ixgbe、i40e、mlx5)默认开启 RSS(Receive Side Scaling),但若未正确配置,所有队列中断可能仍落到同一个 CPU 上。
- 查当前 RSS 队列数:ethtool -l eth0(看 Combined 或 RX 队列数)
- 查中断亲和性:cat /proc/irq/*/smp_affinity_list 2>/dev/null | grep -A1 "eth0",确认每个队列中断是否分散到不同 CPU
- 手动均衡(示例:将 eth0 的 8 个 RX 队列均匀绑到 cpu0–cpu7):
echo 0 > /proc/irq/$(cat /proc/interrupts | grep "eth0-TxRx-0" | awk '{print $1}' | sed 's/://')/smp_affinity_list
依此类推设置 1~7;更稳妥用脚本或 irqbalance(确保它没被禁用且配置合理)
排查驱动与协议栈瓶颈点
即使中断分散了,若单队列处理慢,仍可能压垮对应 CPU。常见瓶颈包括:
- 小包风暴:MTU=1500 的包,每秒 50 万 pkt 就足以打满单核 softirq 处理能力。用 tcpdump -i eth0 -c 1000 -w /tmp/pkts.pcap 2>/dev/null & & ss -i 结合 ifconfig 看 RX packets/sec 和 errs/drop,确认是否丢包伴随高 softirq
- GRO/LRO 开启不当:GRO 在软中断中聚合,反而增加开销。对小包场景可关闭:ethtool -K eth0 gro off(LRO 通常硬件做,无需关)
- Netfilter 规则过多:iptables/nftables 的 INPUT 链规则会在 net_rx 软中断上下文执行(尤其是 raw 和 mangle 表)。用 nft list ruleset | wc -l 或 iptables -t raw -L -n -v 查复杂度,精简非必要规则
内核参数与应用层协同调优
纯靠调参不能替代架构优化,但能缓解短期压力:
- 降低单次软中断处理包数上限,避免 monopolize:echo 64 > /proc/sys/net/core/netdev_budget(默认 300,太大会卡住调度;64~128 较稳)
- 启用 RPS(Receive Packet Steering)作为 RSS 补充(尤其虚拟化或老网卡):
echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus(十六进制掩码,f=cpu0–3) - 应用层配合:避免单连接高频小包(如 HTTP/1.1 不复用、日志直写 socket)。改用批量上报、启用 TCP_NODELAY+writev、或切到 UDP+自定义批处理










