Prhub

#49671 [Bugfix][KV Offloading] Defer request finalization until final store

原始 PR 作者 Palaiologos1453 合并时间 2026-07-26 04:58 文件变更 3 提交数 5 评论 6 代码增减 +111 / -58

执行摘要

推迟请求完成通知,防止 KV 卸载 EngineCore 崩溃

Issue #49635 报告了 KV offloading 的 EngineCore 崩溃:当请求完成时,request_finished 立即调用 manager.on_request_finished,而该请求的最终 KV 块存储作业可能尚未提交。manager 因此删除 _req_state,随后 _build_store_jobs 中的 prepare_store 引用已删除的状态导致 KeyError,使 EngineCore 崩溃。此修复确保 manager 在所有 final store jobs 构建完成后再接收通知。

该 PR 修复了生产环境中的关键时序 bug,设计讨论体现了良好的信号集中化策略。值得阅读以理解 KV offloading 的请求生命周期管理。对于使用 KV offloading 的部署,建议尽快合入。

讨论亮点
  1. 设计讨论:orozery 提供了一个替代修复方案(fa07027d),建议用统一中心化结构处理完成信号。作者采纳并适配了测试,形成 ecf6bc52af。
  2. 生产验证:nilig 在原始 issue 集群上部署验证,单请求和 16/100 突发无 EngineCore 重启,确认修复有效。
  3. 断言保留:orozery 强调不应删除 manager 中的严格断言,作者保留该断言。

实现拆解

  1. 在 RequestOffloadState 中添加 finished_signaled 字段,标记是否已向 manager 发送完成信号。
  2. 移除 _maybe_cleanup_finished_req 方法,改为在 build_connector_meta 中顺序调用 _build_store_jobs 后统一遍历 finished_req_ids:设置 finished_signaled、调用 manager.on_request_finished,若无进行中传输则删除状态。
  3. 修改 request_finished 方法:不再立即通知 manager,仅记录完成状态、更新 offload keys 并将请求加入 finished_req_ids。
  4. 修改 update_connector_output 的清理条件:从检查 is_finished() 改为检查 finished_signaled,确保信号已发送后才清理。
  5. 同步修改 reset_cache 中的清理逻辑,防止重复或遗漏。
  6. 更新测试:调整 test_last_block_offloaded_at_request_finish 断言为 req_status 被清理;重命名并修改 test_on_request_finished_is_not_deferred_until_store_completion 为 test_on_request_finished_not_deferred_until_store_completion,修正 docstring 和期望;测试运行器 _run 在循环条件、EOS 后继续条件中加入 finished_req_ids 检测,确保最终存储步骤完全执行。
文件 模块 状态 重要度
vllm/distributed/kv_transfer/kv_connector/v1/offloading/scheduler.py 卸载调度 modified 7.43
tests/v1/kv_connector/unit/offloading_connector/test_scheduler.py 卸载测试 modified 7.47
tests/v1/kv_connector/unit/offloading_connector/utils.py 测试工具 modified 5.15

关键符号

_maybe_cleanup_finished_req request_finished build_connector_meta update_connector_output reset_cache

关键源码片段

vllm/distributed/kv_transfer/kv_connector/v1/offloading/scheduler.py core-logic

核心逻辑修改:重构请求完成通知时序,添加 finished_signaled 标记,修改 build_connector_meta、update_connector_output、request_finished 等关键方法。

# vllm/distributed/kv_transfer/kv_connector/v1/offloading/scheduler.py# RequestOffloadState 新增字段
@dataclass(slots=True)
class RequestOffloadState:
    # ... 原有字段 ...
    # True once on_request_finished has been signaled to the manager.
    finished_signaled: bool = False# build_connector_meta 方法改造(关键部分)
def build_connector_meta(self, scheduler_output: SchedulerOutput) -> KVConnectorMetadata:
    # ... 构建 store_jobs ( 调用 _build_store_jobs) ...
​
    # 所有 finished 请求的 final store jobs 已通过 prepare_store 提交,
    # 现在可以安全地发送完成信号。注意:complete_store 可能仍异步进行。
    for req_id in scheduler_output.finished_req_ids or ():
        req_status = self._req_status.get(req_id)
        if req_status is None:
            continue
        req_status.finished_signaled = True
        self.manager.on_request_finished(req_status.req_context)
        if not req_status.transfer_jobs:
            # 没有进行中的传输,直接清理状态
            del self._req_status[req_id]
​
    # ... 返回 metadata ...# update_connector_output 中清理条件变更
def update_connector_output(self, connector_output: KVConnectorOutput):
    # ... 处理 job completion ...
    req_status.transfer_jobs.remove(job_id)
    # 之前 : if not req_status.transfer_jobs and req_status.req.is_finished()
    # 现在 : 必须等到 finished_signaled 后才清理,避免过早删除
    if req_status.finished_signaled and not req_status.transfer_jobs:
        del self._req_status[job_status.req_id]

评论区精华

完成信号中心化建议 设计

orozery 在审阅中提供了一个替代修复(fa07027d),建议将完成信号集中到 build_connector_meta 中,避免分散在多处逻辑,并简化 request_finished。

结论:作者采纳该建议,在 ecf6bc52af 中实现中心化结构并调整测试适配。 · 已解决

生产环境验证 测试

nilig 在原始 issue 的集群上部署 PR 补丁,运行单请求和 16/100 突发负载,未发生 EngineCore 重启,确认修复有效。

结论:补丁通过生产环境验证。 · 已解决

保留 Manager 严格断言 设计

orozery 指出不应移除 manager 中的断言,断言有助于未来检测回归,应保持严格模式。

结论:作者保留 manager 中的严格断言,未删除。 · 已解决

风险与影响

核心变更影响 KV offloading 的生命周期,可能引发以下风险:

  • 若 finished_signaled 在某些路径(如 reset_cache)下未正确设置,可能导致请求状态泄漏或重复清理。
  • 时序依赖:build_connector_meta 必须在每次调度步骤中正确调用,如果未来重构此方法而忽略 finalization 部分,可能 reintroduce 该 bug。
  • 测试覆盖了主要场景,但未覆盖多请求并发、大 burst 等所有边缘情况,虽有生产验证仍存在一定风险。

影响范围仅限于使用 KV offloading(OffloadingConnector)的用户,且仅涉及请求完成与 KV 存储的交互时序。不改变其他功能。修复后消除了特定配置下的 EngineCore 崩溃,提升了系统稳定性。

核心生命周期变更 Manager 断言依赖

关联 Issue

#49635 [Bug]: Final KV offload store after request finalization crashes EngineCore

完整报告

参与讨论