读 disaggregation 源码树:prefill、decode 与 transfer backend#

这章解决什么问题#

代码导读前面已经把入口、协议、scheduler、bench_one_batch.py 和 observability 树都拉回主线了,但还有一棵很容易让读者直接迷路的源码树没有被正式导读:python/sglang/srt/disaggregation/。这里面同时有:

  • prefill.py
  • decode.py
  • encode_receiver.py
  • common/
  • base/
  • fake/
  • mooncake/
  • nixl/
  • mori/
  • ascend/

如果不把这棵树的阅读顺序讲清楚,它很容易看起来像一堆传输后端杂糅在一起。

为什么这层值得专门成章#

因为 disaggregation 在整本书里已经不是边角料了:

  • 调度章节已经写了 bootstrap/prealloc/transfer 队列
  • RequestStage 章节已经写了 transfer 相关阶段
  • 扩展与调试章节也写了 disaggregation 排障工作流

既然它已经进入主线,那么代码导读也应该给它一条清晰的源码阅读路径。

一张图:这棵树不是横向散开的,而是有层次的#

这张图解决的理解障碍是:很多人第一次看 disaggregation/ 目录时,只能看到很多 backend 名字,却看不出主干层次。

flowchart TD
    Root["disaggregation/"] --> Core["prefill.py / decode.py / utils.py"]
    Root --> Base["base/ / common/"]
    Root --> Backend["fake / mooncake / nixl / mori / ascend"]
    Root --> Encode["encode_receiver.py / encode_server.py"]

这张图比纯文字多解释的一点是:backend 不是主线的起点,真正更稳的入口是 prefill.py / decode.pybase/common

最稳的阅读顺序是什么#

建议按这个顺序:

  1. 先读 utils.py 里与 disaggregation mode、transfer backend 相关的抽象
  2. 再读 prefill.pydecode.py
  3. 再读 base/conn.pycommon/conn.py
  4. 最后再按需要深入具体 backend,例如 mooncake/conn.pynixl/conn.py

这样读的好处是:你先建立主线,再读变体,而不是一开始就被某个 backend 的实现噪音淹没。

为什么 prefill.pydecode.py 是真正的主线#

因为这里最接近“系统真正要做什么”:

  • prefill 侧怎样准备 KV / bootstrap / transfer
  • decode 侧怎样接 KV / prealloc / waiting / forward

也就是说,这两个文件回答的是角色分工;而具体 backend 文件回答的是“角色之间怎么传”。

如果一开始就先看 mooncake/conn.py 这种大型 backend 文件,你会更容易先记住 transport 细节,而不是系统角色。

base/common/ 为什么值得在 backend 之前看#

因为它们定义了 backend 共用的连接、poll、KVArgs、staging 等抽象。更准确地说:

  • base/ 更像接口与最小共同模型
  • common/ 更像 backend 共享实现与 staging 逻辑

这样读的收益很明显:后面看具体 backend 时,你知道哪些是共性,哪些是特性。

为什么 mooncake/conn.py 看起来特别大#

因为它不仅实现 transport,还承接了:

  • staging
  • bootstrap room
  • session 追踪
  • transfer queues
  • failure / timeout 处理

这说明它不是一个“只负责发数据”的小模块,而是一个更接近端到端后端实现的运行时组件。也正因为这样,本章才更强调不要把它当作第一入口。

encode_receiver.py / encode_server.py 为什么也应该纳入阅读路径#

因为 encoder disaggregation 是这棵树里的另一条正式主线。它解释的不是 decode KV transfer,而是多模态或 encoder 侧的数据转运逻辑。把它们拉进来,代码导读才不会把 disaggregation 误写成“只有 prefill/decode KV cache”的故事。

这层和调度 / 维护章节怎样回扣#

这棵树天然会和前面章节形成强回扣:

  • 调度与内存:看队列与 transfer 阶段
  • RequestStage:看 bootstrap / transfer 的时间切片
  • 扩展与调试:看 placement / transfer / backend 失衡如何落到这棵树

这就是为什么它值得单独导读,而不是只在需要时临时 grep。

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

1. 把 backend 文件当成主线入口#

这样最容易丢掉系统角色分工。

2. 以为 disaggregation 只是 transport 层#

实际上它已经影响排队、时间线、请求角色和故障模式。

3. 只盯一个 backend#

你会更难区分共性设计和 backend 特性。

如果你要顺着这棵树真正读进去,先怎么走#

建议按这个顺序:

  1. utils.py
  2. prefill.py
  3. decode.py
  4. base/conn.py
  5. common/conn.py
  6. 具体 backend(例如 mooncake/conn.py

小结#

这一章真正想补齐的,是代码导读里对另一棵大树的稳定入口:

  • 不是从最大 backend 文件开始
  • 而是先从角色主线、再到共享抽象、最后到具体 backend

到这里,代码导读对 disaggregation/ 这棵树也不再是空白。