4. 多队列技术原理:RSS(Receive Side Scaling)核心概念

随着网络带宽从 1Gbps 向 10Gbps、25Gbps 乃至 100Gbps 演进,单核 CPU 已无法独立完成线速收包处理。RSS(Receive Side Scaling,接收端缩放)是网卡多队列技术的基石,它允许网卡将入站数据流分散到多个硬件接收队列,进而分发至不同 CPU 核心并行处理,从根本上消除单核瓶颈。

4.1 RSS 解决的问题:单队列瓶颈

在传统单队列 NIC 模型中,所有入站数据包共享一个接收描述符环(RX Ring),由单个 CPU 核心负责中断处理与协议栈上送。该模型存在三个致命缺陷:

  • 中断风暴:高吞吐下单个 CPU 被中断淹没,无法调度用户态进程。
  • 缓存抖动:单核 L1/L2 缓存无法容纳海量连接上下文,频繁 cache miss。
  • 锁竞争:协议栈全局锁(如 sock_alloc)在单核上无意义,但多核场景下若仍由单核处理,则成为伪共享瓶颈。
性能指标对比: 在 10Gbps 线速下,单队列方案收包吞吐通常不超过 2.5 Mpps(百万包/秒),而启用 RSS 多队列后,8 队列可线性扩展至 18–20 Mpps,CPU 利用率从单核 100% 降为每核 12–15%。

4.2 RSS 核心机制:哈希分发

RSS 的核心是一个可编程的 Toeplitz 哈希引擎,位于网卡 MAC 层与 DMA 引擎之间。每个入站数据包经过哈希计算后,其结果用于索引一个重定向表(Indirection Table),从而决定该包进入哪个接收队列。

关键点: RSS 哈希是确定性的——同一五元组(源IP、目的IP、源端口、目的端口、协议)始终映射到同一队列,保证 TCP 流的有序性;不同流则均匀散列到不同队列,实现并行。

4.2.1 哈希输入元组

协议类型 哈希输入字段 典型哈希键长度
IPv4 TCP/UDP 源IP + 目的IP + 源端口 + 目的端口 40 字节(4+4+2+2)
IPv4 仅IP 源IP + 目的IP 8 字节
IPv6 TCP/UDP 源IP(128bit) + 目的IP(128bit) + 端口 36 字节
IPv4/IPv6 隧道 内层 IP 头字段(需网卡支持) 可变

4.2.2 重定向表与队列映射

哈希值(通常为 32 位)并不直接对应队列编号,而是通过一个 间接表(Indirection Table,IT) 进行映射。IT 的大小通常为 128 或 512 项,每项存储一个队列 ID(0 ~ N-1)。

// 伪代码:RSS 队列选择流程
uint32_t hash = toeplitz_hash(packet_header, rss_key);
uint32_t index = hash & (indirection_table_size - 1);
uint16_t queue_id = indirection_table[index];
// 将 packet DMA 到 queue_id 对应的 RX Ring
注意: 间接表大小必须是 2 的幂,且与硬件队列数无关。例如 128 项的 IT 可映射到 16 个队列,每 8 个连续槽位指向同一队列,实现加权分发。

4.3 RSS 硬件架构与数据流

下图展示了 RSS 在网卡内部的完整处理流水线:

RSS 硬件架构与数据流 RSS 硬件架构与数据流 物理介质 MAC 层 Toeplitz 哈希 间接表 DMA 引擎 RX Queue 0 RX Queue 1 RX Queue 2 RX Queue 3 硬件队列 CPU 0 CPU 1 CPU 2 CPU 3 说明: 1. 哈希引擎使用 40 字节 RSS Key 2. 间接表大小 = 128 项 3. 同一流始终映射到同一队列

4.4 RSS 关键参数与配置

Linux 下通过 ethtool 工具可完整查看和调整 RSS 参数:

# 查看网卡 RSS 队列数
ethtool -l eth0
# 输出示例:
#   Combined: 8
#   RX:        8
#   TX:        8

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

# 查看当前 RSS 哈希配置
ethtool -x eth0
# 输出示例:
#   RSS hash function: toeplitz
#   RSS hash key: 6d:5a:56:da:25:5b:0e:c2:41:67:25:3d:43:a3:8f:b0:...
#   RSS indirection table: 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 ...

# 自定义 RSS 哈希键(40 字节十六进制)
ethtool -X eth0 hkey 6d:5a:56:da:25:5b:0e:c2:41:67:25:3d:43:a3:8f:b0:...

# 设置 RSS 哈希输入元组(仅 IPv4 TCP)
ethtool -N eth0 rx-flow-hash tcp4 sdfn

4.4.1 哈希输入元组标志

标志 含义 典型使用场景
s 源 IP 地址 基础负载均衡
d 目的 IP 地址 基础负载均衡
f IP 协议号(如 TCP=6, UDP=17) 区分协议类型
n 源端口 细粒度流分发
r 目的端口 细粒度流分发

4.5 RSS 与 CPU 亲和性的联动

RSS 仅保证数据包被分发到不同硬件队列,但队列的中断处理程序最终运行在哪个 CPU 核心上,由 中断亲和性(IRQ Affinity) 决定。两者必须联动配置才能实现真正的负载均衡:

  1. RSS 层:通过哈希将流散列到不同队列,避免单队列拥塞。
  2. IRQ Affinity 层:将每个队列的中断绑定到指定 CPU 核心,确保中断处理与后续协议栈处理在同一核心上完成,最大化缓存局部性。
最佳实践: 在 16 核服务器上,若网卡支持 8 个 RSS 队列,应将队列 0–7 的中断分别绑定到 CPU 0–7,并确保 CPU 0–7 上的其他非必要中断(如存储、时钟)被迁移到 CPU 8–15,避免干扰。

4.6 RSS 的局限性

  • 哈希冲突:不同流可能映射到同一队列,导致局部热点。可通过增大间接表或使用对称哈希缓解。
  • 不支持 UDP 多流:UDP 无连接概念,部分网卡默认仅对 IP 对做哈希,导致所有 UDP 流量进入同一队列。
  • 虚拟化环境:在 SR-IOV VF 中,RSS 功能取决于物理网卡和 PF 驱动支持,部分 VF 仅支持单队列。
  • 无法感知应用负载:RSS 是纯硬件哈希,无法根据 CPU 当前利用率动态调整分发策略。
排查提示: 若发现某个 CPU 核心的软中断(si)利用率持续高于其他核心,使用 cat /proc/interrupts | grep eth0 检查各队列中断分布,再通过 ethtool -x eth0 验证间接表是否均匀映射。