Prhub

#24772 Fix PD bootstrap failure handling

原始 PR 作者 yhyang201 合并时间 2026-05-10 19:02 文件变更 1 提交数 3 评论 9 代码增减 +3 / -0

执行摘要

修复 PD 引导失败时状态异常与属性错误

在 PD(Prefill/Decode)分离部署场景下,若预填充服务器 bootstrap 失败(如 prefilling 端宕机),_setup_bootstrap_infos 虽将 conclude_state 标记为 Failed,但未立即返回,导致下游 update_status(WaitingForInput) 覆盖失败状态,且 bootstrap_infos 可能因未定义而触发 AttributeError。PR body 明确说明动机:修复 bootstrap info 获取失败时的异常处理。

建议合入。该 PR 是典型的边界条件修复,改动量小且逻辑正确,经 review 确认可读。对于关注 PD 部署稳定性的团队,值得了解该修复以避免生产环境中的无声错误。

讨论亮点

Reviewer ShangmingCai 对提交 702e0c5 中的 data_parallel_controller.py 变更提出质疑,认为在 PD-prefill 模式下直接跳过外部 routed_dp_rank 会破坏 bootstrap_room 与 DP rank 的映射契约。作者 yhyang201 同意该观点,并指出 main 分支已通过 #23882 更好地处理该问题,因此回退了该 commit。最终 reviewer 确认“common backend modification looks good”并批准。

实现拆解

  1. _setup_bootstrap_infos 中失败路径显式置 None:当 _get_bootstrap_info_from_server 返回 Noneconclude_state 设为 Failed 后,在 return 前添加 self.bootstrap_infos = None,使下游检查时触发 None 检查而非 AttributeError
  2. _setup_bootstrap_infos 调用后立即检查失败状态:在 kv_mgr.update_status(self.bootstrap_room, KVPoll.WaitingForInput) 前插入 if self.conclude_state == KVPoll.Failed: return,避免失败请求被错误地转为 WaitingForInput
  3. 修复涉及的文件:仅 python/sglang/srt/disaggregation/common/conn.py,改动量 +3/-0。
  4. 回退多余变更:提交历史显示作者先尝试引入 data_parallel_controller.py 中的外部 DP rank 路由跳过逻辑,经 review 讨论后认为由 #23882 处理更恰当,随即 revert 该部分,最终 PR 仅保留 conn.py 的 3 行核心修复。
文件 模块 状态 重要度
python/sglang/srt/disaggregation/common/conn.py 连接模块 modified 5.16

关键符号

PrefillStatePoll.init PrefillStatePoll._setup_bootstrap_infos

关键源码片段

python/sglang/srt/disaggregation/common/conn.py core-logic

唯一的修改文件,包含 PD bootstrap 失败的恢复逻辑:置空 `bootstrap_infos` 并在失败后跳过 `WaitingForInput` 状态更新。

# python/sglang/srt/disaggregation/common/conn.py
# 在 PrefillStatePoll.init 方法中,
# 调用 _setup_bootstrap_infos 之后检查 bootstrap 是否失败
self.prefill_dp_rank = prefill_dp_rank
self._setup_bootstrap_infos()
# 新增:若 bootstrap 已标记失败,则跳过 WaitingForInput 状态更新
if self.conclude_state == KVPoll.Failed:
    return
self.kv_mgr.update_status(self.bootstrap_room, KVPoll.WaitingForInput)def _setup_bootstrap_infos(self):
    """Fetch bootstrap info from prefill server for all ranks."""
    all_bootstrap_infos = []
    for target_cp_rank in self.target_cp_ranks:
        bootstrap_key = f"{self.bootstrap_addr}_{self.prefill_dp_rank}_{target_cp_rank}_{self.target_tp_rank}"
        if bootstrap_key not in self.kv_mgr.connection_pool:
            bootstrap_infos = []
            for target_tp_rank in self.target_tp_ranks:
                for target_pp_rank in reversed(self.target_pp_ranks):
                    bootstrap_info = self._get_bootstrap_info_from_server(...)
                    if bootstrap_info is not None:
                        bootstrap_infos.append(bootstrap_info)
                    else:
                        self.kv_mgr.record_failure(self.bootstrap_room, ...)
                        self.conclude_state = KVPoll.Failed
                        self.kv_mgr.update_status(self.bootstrap_room, KVPoll.Failed)
                        self.bootstrap_infos = None # 新增:避免下游 AttributeError
                        return
            # ... 成功路径
        # ...

评论区精华

外部 DP rank 路由跳过逻辑是否应合入 设计

Reviewer ShangmingCai 对 `data_parallel_controller.py` 中跳过外部 `routed_dp_rank` 的修改提出质疑,认为在 PD-prefill 模式下会破坏 `bootstrap_room` 与 DP rank 的映射。作者 yhyang201 回应同意,并指出 main 分支已通过 #23882 处理,决定 revert。

结论:回退 `data_parallel_controller.py` 的变更,PR 仅保留 conn.py 的核心修复。 · 已解决

风险与影响

风险极低。改动仅 3 行,逻辑清晰:失败路径提前返回并置空引用。可能存在的风险是:其他依赖 _setup_bootstrap_infos 中失败后仍执行后续逻辑的地方未发现,但代码显式 return 已避免执行路径扩散;此外 self.bootstrap_infos = None 可能被下游代码 assert len(self.bootstrap_infos) > 0 直接捕获,但失败路径已提前返回,不会到达断言。

直接影响 PD 分离部署模式下 bootstrap 失败的请求:此前会导致 AttributeError 或状态错误标记,修复后将正确将请求标记为 Failed。影响范围仅限于 conn.py 中的 PrefillStatePoll 初始化流程,不涉及其他模块。由于未涉及配置变更或 API 调整,对用户透明。

核心路径变更

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论