4. 队列与调度机制

当多个队列同时有报文等待发送时,出端口在某一时刻只能送出一个报文,调度算法决定“下一个轮到谁”。在 NVIDIA Spectrum 系列交换机上,调度不是孤立存在的,它建立在“端口 → 流量类别 TC → 队列”的映射之上,并与缓存管理、PFC/ECN 等拥塞控制手段协同工作。理解 SP、WRR、DWRR、WFQ 的差异,核心是理解三件事:优先级是否绝对、权重如何被消耗、以及空闲带宽如何被再利用。

一、四种调度算法的本质差异

SP(Strict Priority,严格优先级):调度器永远先服务最高优先级队列,只有高优先级队列为空时才看下一级。它的优点是时延确定、抖动极小,适合承载控制面协议、RoCEv2 的 CNP 拥塞通知、BGP/LLDP 等对时延敏感且带宽需求小的流量。缺点是低优先级队列可能被“饿死”——只要高优先级持续有流量,低优先级就得不到服务。因此 SP 通常只用于最高 1~2 个队列,其余队列交给加权类算法。

WRR(Weighted Round Robin,加权轮询):按权重比例轮流服务各队列,权重决定的是“每轮发送的报文个数”。例如权重 3:1,则每轮队列 A 发 3 个报文、队列 B 发 1 个报文。问题在于:如果 A 的报文是 1500 字节、B 的报文是 64 字节,实际带宽比会严重偏离 3:1。WRR 的公平性建立在“报文长度相近”的假设上,在混合包长的数据中心流量中容易失真。

DWRR(Deficit Weighted Round Robin,差额加权轮询):为每个队列维护一个“差额计数器”(Deficit Counter)。每轮给队列增加与其权重成正比的信用值,队列每发送一个报文就扣除该报文的字节数;若信用不足以发送队首报文,则本轮跳过,信用累积到下一轮。DWRR 以字节而非报文为计量单位,因此即使包长差异很大,长期带宽比例仍能逼近权重比,是 Spectrum 上最常用的加权调度方式。

WFQ(Weighted Fair Queuing,加权公平队列):理论上按“虚拟时间”为每个报文计算一个完成时刻,调度器总是发送虚拟完成时间最小的报文,从而在任意时间尺度上都逼近权重比例,公平性最好、时延上界最紧。代价是实现复杂、需要维护虚拟时钟和排序结构,硬件开销大。Spectrum 上通常以 DWRR 作为 WFQ 的工程近似,在绝大多数场景下二者效果接近。

Spectrum 出端口调度:队列 → 调度器 → 端口 队列 Q7 (TC7) 控制/CNP Q5 (TC5) 存储/关键业务 Q3 (TC3) 普通业务 Q1 (TC1) 尽力而为 出端口调度器 SP 严格优先级组 Q7 绝对优先;Q7 空才轮到 Q5 加权调度组(DWRR / WRR / WFQ) Q5 权重 40 | Q3 权重 40 | Q1 权重 20 DWRR:按字节扣减差额信用 WRR:按报文个数轮询 WFQ:按虚拟完成时间排序 选中报文 出端口 100G 线速发送 关键差异速览 SP:时延最小,低优先级可能饿死 → 仅用于最高 1~2 个队列 WRR:按包数轮询,混合包长下带宽比例失真 DWRR:按字节计信用,长期带宽逼近权重比,Spectrum 主力 WFQ:虚拟时间排序,公平性最优但硬件开销大,常用 DWRR 近似

二、Spectrum 上的实现差异

Spectrum 的端口调度采用分层结构:先做 SP 组间仲裁,再在加权组内做加权轮询。这意味着“SP + DWRR”混合模式是常态——把最敏感的 1~2 个队列放进 SP 组,其余队列放进加权组按权重分配。这种分层设计既保证了关键流量的低时延,又避免了低优先级队列被完全饿死。

在加权组内,Spectrum 支持为每个队列配置权重(通常为 1~127 的整数),并支持将某个队列的权重设为 0 表示“仅使用剩余带宽”。DWRR 的差额计数器在硬件中按队列维护,每轮增加的信用与权重成正比,发送时按报文实际字节数扣减。当所有队列的信用都不足以发送队首报文时,调度器会进入“空闲信用累积”状态,下一轮信用继续叠加,从而保证长期比例不失真。

WFQ 在 Spectrum 上并非以独立硬件队列形式实现,而是通过 DWRR 的精细权重配置来逼近。对于绝大多数数据中心场景,DWRR 与 WFQ 的带宽分配误差在 1% 以内,而 DWRR 的实现开销更低、配置更直观。因此选型时不必纠结“是否必须 WFQ”,而应关注权重比例是否合理、包长分布是否极端。

三、选型依据与配置示例

选型可以按以下逻辑判断:

  • 时延敏感、带宽小(控制协议、CNP、BGP):放入 SP 组,绝对优先。
  • 时延敏感、带宽中等(存储前端、数据库同步):放入 SP 组或加权组高权重,配合 ECN。
  • 带宽敏感、时延可容忍(备份、大数据、普通业务):放入加权组,按业务价值分配权重。
  • 包长差异大(混合 64B 小包与 1500B 大包):优先 DWRR,避免 WRR 的比例失真。
  • 需要严格比例保证(多租户带宽隔离):DWRR 权重按字节比例配置,必要时用 WFQ 近似。

以下是一个 Spectrum 上的典型配置示例(以 4 个队列为例,权重为示例值,需按实际业务调整):

# 将流量类别映射到队列
tc qdisc add dev swp1 clsact
tc filter add dev swp1 ingress protocol ip prio 1 \
  flower ip_tos 0xb8 action skbedit priority 7   # EF → Q7
tc filter add dev swp1 ingress protocol ip prio 2 \
  flower ip_tos 0x48 action skbedit priority 5   # AF21 → Q5
tc filter add dev swp1 ingress protocol ip prio 3 \
  flower ip_tos 0x20 action skbedit priority 3   # AF11 → Q3
tc filter add dev swp1 ingress protocol ip prio 4 \
  flower action skbedit priority 1               # 默认 → Q1

# 配置 DWRR 权重(示例:Q5:Q3:Q1 = 40:40:20)
# Spectrum 通过 SDK/CLI 配置端口调度权重
# 以下为示意性命令,具体以设备 CLI 为准
interface swp1
  qos scheduler dwrr
  qos queue 5 weight 40
  qos queue 3 weight 40
  qos queue 1 weight 20
  qos queue 7 strict-priority

配置完成后,验证的关键是观察各队列的实际发送字节数比例是否接近权重比。可以在端口上查看队列统计:

# 查看各队列发送字节数与丢包
show interface swp1 queue-stats
# 输出示例(示意):
# Queue  Tx Bytes    Tx Packets   Drops
# Q7     1,240,000   8,200        0
# Q5     48,600,000  32,400       0
# Q3     47,900,000  31,900       0
# Q1     24,100,000  16,100       0

若 Q5 与 Q3 的发送字节数接近 1:1、Q1 约为它们的一半,说明 40:40:20 的权重生效。若 Q1 的字节数远低于预期,需检查是否有 SP 队列长期占用端口,或加权组内是否存在信用累积异常。若发现某队列持续丢包而其他队列未跑满,则可能是权重配置过低或缓存不足,需要结合 ECN/PFC 进一步排查。

SP 与加权调度可以共存:把最敏感的队列设为 strict-priority,其余队列用 DWRR 分配权重,是 Spectrum 上最稳妥的默认组合。权重配置后务必用队列统计验证实际字节比例,而不是只看配置是否下发成功。
WRR 在混合包长场景下容易产生带宽比例偏差,若业务中同时存在 64B 小包和 1500B 大包,建议直接使用 DWRR。将低优先级队列权重设为 0 时,该队列只能使用剩余带宽,在高优先级流量持续时可能长期得不到服务,需谨慎使用。