ksoftirqd 持续高 CPU 是因网卡收包积压导致 softnet backlog 过高,非软中断本身繁忙;真实瓶颈在 NIC 驱动或硬件收包路径,如 RSS 不均、GRO 开启但应用不消费、NAPI 轮询不足。

为什么 ksoftirqd 持续吃高 CPU 且 softnet backlog 居高不下
这不是软中断本身太忙,而是网卡收包后来不及处理,导致 softnet_data->input_pkt_queue 积压。一旦 backlog 超过 net.core.netdev_max_backlog(默认 1000),内核会丢包并触发更频繁的 softirq 调度,形成恶性循环——ksoftirqd 看似“忙”,实则是被积压队列拖住的救火队员。
- 典型现象:
cat /proc/net/softnet_stat中每行第 2 列(drop)持续增长,第 1 列(processed)远高于第 3 列(time_squeeze) - 真实瓶颈往往在 NIC 驱动层或硬件收包路径,比如 RSS 队列未均分、GRO 开启但应用不消费、NAPI poll 轮询量不足
-
ksoftirqd占用率高只是表象,不能靠调高vm.swappiness或关 irqbalance 来解决
net.core.netdev_max_backlog 改大就能缓解吗
不能盲目调大。该值只是队列上限,不是性能加速器。设得过大反而延长延迟、掩盖真实瓶颈,还可能因内存碎片导致分配失败(见 dmesg 中 softnet_alloc_recv_skb_failed)。
- 合理范围:2000–5000,需配合
net.core.dev_weight和 NAPIweight同步调整 - 必须确认硬件支持:部分老网卡(如 e1000e)在 backlog > 2048 时触发额外锁竞争,CPU 反而更卡
- 改完要验证:
watch -n1 'cat /proc/net/softnet_stat | cut -d" " -f1,2,3',观察 drop 是否下降、time_squeeze 是否减少
RSS、RPS、RFS 该怎么配才不打架
RSS(硬件多队列)优先级最高,RPS 是软件模拟,RFS 是流亲和增强。三者混用易冲突,尤其 RPS 在开启 RSS 后基本无用,还增加 cache miss。
- 有 RSS 支持(ixgbe、i40e、mlx5):关闭 RPS(
echo 0 > /sys/class/net/eth0/queues/rx-0/rps_cpus),只调 RSS 队列数和 IRQ 绑核 - 无 RSS(如 vmxnet3、virtio):启用 RPS + RFS,但
rps_sock_flow_entries至少设为 32768,否则流哈希碰撞严重 - RFS 依赖
net.core.rps_flow_cnt,若应用短连接多,建议设为 65536;否则默认 32768 即可
哪些网卡参数改动最立竿见影
别碰 txqueuelen 或 ethtool -G ring buffer 大小——它们影响的是发包或 DMA 缓存,对 softnet backlog 几乎无感。真正关键的是 NAPI 和 GRO/GSO 控制点。
- 降低单次 NAPI 处理上限:
echo 64 > /sys/class/net/eth0/napi_defer_hard_irqs(仅支持较新驱动),或调小net.core.dev_weight(默认 64 → 32) - 禁用 GRO(如果上层是 UDP 或 TLS 流量):
ethtool -K eth0 gro off,避免大包重组后无法及时分发 - 确认
net.ipv4.tcp_rmem第三项(max)不低于 4M,否则 socket 接收缓冲区小,会卡住 softnet 消费链路
真正卡点常在驱动与协议栈交界处:比如 ixgbe 的 InterruptThrottleRate 设太高会导致中断合并过度,RSS 队列空转;而 virtio-net 的 vq_rx ring size 不够则直接堵死 vhost 内核线程。这些细节比 sysctl 参数更值得盯住。










