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 上的实现差异
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 进一步排查。