Disaggregation、transfer 与路由失衡的排障路径#

这章解决什么问题#

扩展与调试前面已经分别讲了 /v1/loads、routing signal、watchdog、RequestStage 时间线和更深的 cache/storage backend 故障面,但还缺一条更接近现场的复合型工作流:当你怀疑问题和 disaggregation、transfer 或路由失衡一起缠在时,应该怎样把这些信号串起来,而不是在 controller、scheduler、transfer backend 和 metrics 之间来回跳。

这一章就是把这条复合型排障路径压出来。

为什么这类问题特别容易误判#

因为它往往会同时表现成几种症状:

  • 请求被放错 DP rank
  • 某些 bootstrap / transfer 队列积压
  • /v1/loads 看起来不均匀
  • 请求时间线卡在 transfer 或 decode_prealloc
  • 甚至表面上像普通延迟问题

如果没有明确工作流,维护者很容易各看一半证据,然后得出错误结论。

一张图:这类问题要怎样把多层信号串起来#

这张图解决的理解障碍是:很多人会先看一个面板或者一段日志,但这类问题需要跨 controller、scheduler、RequestStage 和 transfer 状态一起看。

flowchart LR
    Place["placement signal"] --> Loads["/v1/loads"]
    Loads --> Stage["RequestStage timeline"]
    Stage --> Queue["bootstrap / prealloc / transfer queues"]
    Queue --> Backend["transfer backend / staging / mooncake"]

图比纯文字多解释的一点是:这类问题不是单层问题,而是需要按层级逐步收敛。

第一步:先看 placement signal 是否已经不合理#

先确认:

  • 请求是否带了 routed_dp_rank
  • 是否带了 routing_key
  • 当前 LoadBalanceMethod 是什么
  • /v1/loads 返回的各 DP rank 状态是否明显失衡

如果在这一步就已经能看到 placement 明显不合理,那么问题很可能还没到 transfer backend,而是在 controller / routing signal 层。

第二步:再看 RequestStage 时间线卡在哪#

如果 placement 表面上还合理,就去看 ReqTimeStats

  • 卡在 prefill_bootstrap
  • 卡在 prefill_transfer_kv_cache
  • 卡在 decode_prealloc
  • 卡在 decode_transfer
  • 还是已经进入正常 decode_waiting / decode_forward

这一步的价值非常大,因为它能帮助你判断:问题更像“队列结构没推进”,还是“已到传输层但传不动”。

第三步:对照 queue 形态而不是只看总延迟#

这类问题很容易被一句“延迟变高了”掩盖。更有价值的做法是直接看:

  • disagg_prefill_bootstrap_queue
  • disagg_decode_prealloc_queue
  • disagg_decode_transfer_queue
  • 以及是否已有 retracted queue 堆积

队列堆在哪里,往往比平均延迟更接近真正根因。

第四步:最后才深入 transfer backend#

如果前三步已经证明:

  • placement 基本合理
  • 阶段确实卡在 transfer 相关 stage
  • 队列也确实堆在 transfer 相关位置

这时才值得去看具体 transfer backend,例如 staging handler、Mooncake、KV transfer 状态、bootstrap room 对应关系等。

这样做的好处是,避免你把所有“慢”都提前归因给 backend。

这一层最容易出现的误判#

1. 只看 /v1/loads 就断定是 routing 问题#

它只能告诉你分布异常,不足以证明 transfer backend 没问题。

2. 只看 RequestStage 卡在 transfer,就断定是 backend 问题#

也可能是更早层的 placement 导致某个队列过度集中。

3. 只看单个请求#

这类问题很多时候是分布问题,不是单样本问题。

更稳的现场排障顺序#

建议按这个顺序:

  1. 先看 placement signal:routed_dp_rankrouting_keyLoadBalanceMethod
  2. 再看 /v1/loads:各 rank 是否失衡
  3. 再看 RequestStage:卡在哪个阶段
  4. 再看 disaggregation queues:是哪条队列堆住了
  5. 最后才进入具体 transfer backend 或 staging 细节

小结#

这一章真正想补齐的,是扩展与调试里一条典型的“复合型故障工作流”:

  • 不是先猜 backend
  • 也不是先盯单个指标
  • 而是先看 placement,再看阶段,再看队列,最后才看 transport 细节

到这里,扩展与调试部分就不只在讲单个工具或单层信号,而开始提供跨层收敛根因的完整路径。