网卡与驱动调优:RSS、多队列、中断亲和性

网卡,说白了就是服务器和外界打交道的「门卫」。

我见过太多团队,CPU 优化到极致,内存延迟压到个位数,结果一上生产,网卡先扛不住了。丢包、中断风暴、单核打满……问题一个接一个。今天咱们就把网卡这块彻底捋清楚。

为什么网卡会成为瓶颈?

传统网卡只有一个队列。所有数据包进来,都往这一个队列里塞。CPU 呢?也只能一个核去处理这些中断。你想想看,万兆网卡每秒能收上千万个包,一个核根本忙不过来。

我在项目中遇到过,某台机器流量一上来,CPU 0 直接 100%,其他核却在旁边看热闹。这就是典型的「中断不均衡」。

RSS:让多个核一起干活

RSS(Receive Side Scaling)就是解决这个问题的。它让网卡把收到的包,根据哈希值分散到多个队列里。每个队列对应一个 CPU 核,大家各管各的,谁也不抢谁的。

核心原理: 网卡硬件计算数据包的哈希值(通常基于 IP + 端口),然后根据哈希值决定放到哪个队列。

启用 RSS 很简单,但要注意哈希算法。我建议用 Toeplitz 哈希,它比 XOR 哈希更均匀,不容易出现「热点队列」。

# 查看当前 RSS 队列数
ethtool -l eth0

# 设置 RSS 队列数为 4
ethtool -L eth0 combined 4

# 查看 RSS 哈希配置
ethtool -x eth0

嗯,这里要注意:队列数不要超过 CPU 核数。我曾经见过有人设了 16 个队列,但机器只有 8 个核,结果反而因为上下文切换变多了,性能不升反降。

多队列:不只是 RSS

RSS 管的是收包。那发包呢?

现代网卡支持多队列发送(Multi-Queue TX)。每个 CPU 核有自己的发送队列,发数据包时不用抢锁。这在多线程场景下特别重要。

特性 RSS(收) 多队列 TX(发)
作用方向 入站 出站
实现方式 硬件哈希分流 每 CPU 独立队列
关键参数 哈希算法、队列数 队列深度、TX 描述符
常见问题 哈希不均匀 队列锁竞争

我个人习惯,在 DPDK 场景下会把 TX 队列数设成和 CPU 核数一样。但在内核协议栈里,设成核数的一半就够了,因为内核本身有锁开销,队列太多反而浪费。

中断亲和性:把中断绑在正确的核上

光有队列还不够。你得告诉系统:这个队列的中断,交给哪个核去处理。

这就是中断亲和性(IRQ Affinity)。

我的经验: 把网卡中断绑在非业务核上。比如你有 16 个核,0-11 跑业务,12-15 专门处理中断。这样业务核不会被中断打断,缓存命中率更高。
# 查看中断号
cat /proc/interrupts | grep eth0

# 设置中断亲和性(假设中断号 78)
echo 2 > /proc/irq/78/smp_affinity

# 或者用 irqbalance 自动分配
systemctl start irqbalance

我曾经踩过一个坑:irqbalance 默认会把中断均匀分配到所有核上。但如果你有 NUMA 架构,跨 NUMA 访问内存的延迟很高。正确的做法是:把中断绑在同一个 NUMA 节点上的核。

注意: 中断亲和性设置后,要检查是否生效。用 cat /proc/interrupts 看中断分布,如果某个核的中断数明显偏多,说明设置有问题。

实战调优步骤

好了,理论说完了。咱们直接上实战步骤。

  1. 确认网卡型号和驱动版本 —— 有些老驱动不支持多队列,先升级再说。
  2. 设置队列数 —— 用 ethtool -L 设成 CPU 核数或核数的一半。
  3. 配置 RSS 哈希 —— 用 ethtool -X 选择 Toeplitz 哈希,确保四元组(源 IP、目的 IP、源端口、目的端口)都参与哈希。
  4. 绑定中断亲和性 —— 把中断绑在同一个 NUMA 节点上,避免跨节点访问。
  5. 验证效果 —— 用 sar -n DEV 看网卡吞吐,用 mpstat -P ALL 看 CPU 使用率。如果所有核都均匀在干活,说明调优成功了。
一句话总结: 网卡调优的核心,就是让每个 CPU 核都忙起来,别让一个核累死,其他核闲死。

避坑指南

我曾经在 Mellanox 网卡上遇到过一个问题:RSS 哈希默认只用了 IP 和端口的一部分,导致同一个连接的数据包被分到了不同队列。结果应用层收到乱序包,性能直接腰斩。

解决办法:用 ethtool -U 添加自定义流规则,强制同一个五元组走同一个队列。

# 添加流规则:源 IP 192.168.1.1 的流量走队列 0
ethtool -N eth0 flow-type ip4 src-ip 192.168.1.1 action 0

嗯,这个技巧在金融交易场景下特别有用。订单流必须保序,乱序会导致成交记录错乱。

另一个坑:虚拟机场景下,网卡多队列需要宿主机和虚拟机都支持。我建议用 virtio 网卡,它原生支持多队列,性能比 e1000 好很多。

最后说一句:网卡调优不是一劳永逸的。流量模型变了,哈希策略就得跟着调。我每季度都会重新跑一遍压测,看看队列分布是否均匀。毕竟,网络是活的,调优也得跟着活。