Prhub

#40841 [Frontend] DP Supervisor

原始 PR 作者 yewentao256 合并时间 2026-05-22 11:33 文件变更 7 提交数 60 评论 74 代码增减 +1168 / -17

执行摘要

引入 DP Supervisor 支持节点级多端口外部健康聚合

现有外部 DP 模式(--data-parallel-external-lb)启动多个独立 API 服务器,但缺乏统一健康检查和进程监督,与 Kubernetes 探针配合不佳。Issue #40814 提出需要一个节点级别 supervisor 来提供聚合健康端点并管理子进程,使部署更适应 K8s 环境。

值得精读,尤其是 supervisor 的进程模型、信号转发和健康聚合方式。团队可在 K8s 部署中验证默认探针参数适配性。

讨论亮点
  • 架构选择:robertgshaw2-redhat 要求从 threading 切换到 uvicorn(asyncio),以保持项目一致。作者采纳并验证。
  • 健康检查语义:hexfusion 指出 Kubernetes 中 /health(liveness)与 /readyz(readiness)不同,作者区分两者。
  • 状态类简化:robertgshaw2-redhat 认为状态类过于复杂,作者移除 MultiportExternalLBState 等。
  • 探针配置:robertgshaw2-redhat 要求添加探针重试和配置,作者添加了 interval/timeout/threshold 参数。
  • 子进程守护:njhill 建议使用 PR_SET_PDEATHSIG,但最终未包含(unresolved)。

实现拆解

  1. 新增配置与入口:在 cli_args.py 的 FrontendArgs 中添加 data_parallel_supervisor_port、dp_supervisor_probe_interval_s 等探测配置;在 arg_utils.py 中增加 --data-parallel-multi-port-external-lb 标志。入口 serve.py 识别该模式并调用 run_dp_supervisor(),同时与其他 LB 模式互斥。

  2. 参数验证与子进程构建:dp_supervisor.py 的 validate_multi_port_external_lb_args() 函数校验多端口模式的各项约束(端口重叠、size 整除、不支持 gRPC/UDS/HTTPS 等)。_build_vllm_dp_server_args() 为每个本地 rank 创建子进程参数副本,分配端口和 rank。

  3. DPSupervisor 核心:run_dp_supervisor() 启动主流程:启动子进程(multiprocessing.Process),构建 FastAPI 应用并启动 uvicorn 服务器,同时设置后台任务 _monitor_children 定期探测子进程 /health 和 /readyz。收到 SIGINT/SIGTERM 后转发信号至子进程并等待退出。

  4. 测试覆盖:test_dp_supervisor.py 包含单元测试和生命周期集成测试。集成测试使用假的 aiohttp 服务器替代真实子进程,验证健康聚合、关闭序列和子进程崩溃等场景。

  5. 辅助改善:system_utils.py 的 decorate_logs 新增 skip_if_decorated 参数,避免子进程日志被重复装饰。

文件 模块 状态 重要度
vllm/entrypoints/openai/dp_supervisor.py 前端 added 8.89
tests/entrypoints/openai/test_dp_supervisor.py 测试 added 7.76
vllm/entrypoints/cli/serve.py 命令行 modified 6.17
vllm/entrypoints/openai/cli_args.py 前端 modified 5.47
vllm/engine/arg_utils.py 引擎 modified 5.1
vllm/utils/system_utils.py 系统工具 modified 5.4

关键符号

infer_multi_port_external_lb_start_rank validate_multi_port_external_lb_args _build_vllm_dp_server_args _build_vllm_dp_server_env _child_base_url _join_processes_with_timeout _probe_endpoint _build_dp_supervisor_app decorate_logs

关键源码片段

vllm/entrypoints/openai/dp_supervisor.py core-logic

核心实现文件,定义 DPSupervisor 类、参数验证、子进程管理、健康探测和管理员 FastAPI 应用。

def validate_multi_port_external_lb_args(args: argparse.Namespace) -> None:
    # 不支持 gRPC
    if getattr(args, 'grpc', False):
        raise ValueError(
            'Error: --data-parallel-multi-port-external-lb does not support --grpc'
        )
    # 不支持 Unix Domain Socket
    if args.uds is not None:
        raise ValueError(
            'Error: --data-parallel-multi-port-external-lb does not support --uds'
        )
    # 暂不支持 HTTPS
    if any((args.ssl_keyfile, args.ssl_certfile, args.ssl_ca_certs)):
        raise ValueError(
            'Error: --data-parallel-multi-port-external-lb does not support HTTPS yet'
        )
    # 要求 api-server-count 为 1
    if args.api_server_count not in (None, 1):
        raise ValueError(
            'Error: --data-parallel-multi-port-external-lb currently requires '
            '--api-server-count=1'
        )
    # data-parallel-rank 由 supervisor 管理
    if args.data_parallel_rank is not None:
        raise ValueError(
            'Error: --data-parallel-multi-port-external-lb manages child '
            '--data-parallel-rank values internally'
        )
    # 不能与其他 LB 模式混用
    if args.data_parallel_external_lb or args.data_parallel_hybrid_lb:
        raise ValueError(
            'Error: --data-parallel-multi-port-external-lb cannot be combined with '
            '--data-parallel-external-lb or --data-parallel-hybrid-lb'
        )
    # data-parallel-size 必须大于 1
    if args.data_parallel_size < 2:
        raise ValueError(
            'Error: --data-parallel-multi-port-external-lb requires '
            '--data-parallel-size > 1'
        )
​
    local_size = args.data_parallel_size_local
    # local size 必须 >= 2
    if local_size is None or local_size < 2:
        raise ValueError(
            'Error: --data-parallel-multi-port-external-lb requires '
            '--data-parallel-size-local >= 2'
        )
    # local size 不能超过全局 size
    if local_size > args.data_parallel_size:
        raise ValueError(
            'Error: --data-parallel-size-local cannot exceed --data-parallel-size'
        )
    # 全局 size 必须能被 local size 整除
    if args.data_parallel_size % local_size != 0:
        raise ValueError(
            'Error: --data-parallel-size must be divisible by '
            '--data-parallel-size-local'
        )
​
    # 验证 rank 范围不越界
    start_rank = infer_multi_port_external_lb_start_rank(args)
    if start_rank + local_size > args.data_parallel_size:
        raise ValueError(
            'Error: multi-port supervised ranks would exceed --data-parallel-size'
        )
​
    # 确保 supervisor 端口不与 child 端口重叠
    supervisor_port = args.data_parallel_supervisor_port
    child_port_min = args.port
    child_port_max = args.port + local_size - 1
    if child_port_min <= supervisor_port <= child_port_max:
        raise ValueError(
            f'Error: --data-parallel-supervisor-port {supervisor_port} '
            f'overlaps with child rank ports {child_port_min}-{child_port_max}'
        )

评论区精华

使用 uvicorn 替代 threading 作为 Supervisor 服务器框架 设计

robertgshaw2-redhat 建议使用项目已有的 uvicorn(asyncio)替代 threading,以避免混合 asyncio 和 threading 的反模式。

结论:作者重构为 uvicorn,并验证功能正常。 · 已解决

区分健康检查的 liveness 和 readiness 正确性

hexfusion 指出在 Kubernetes 语境下 /health(liveness)和 /readyz(readiness)应有不同语义。在开始阶段和瞬态故障时可能 healthy != ready。

结论:作者采纳,将 /readyz 状态与 /health 区分,SIGTERM 时只标记 ready=false 而非 health=false。 · 已解决

简化状态管理类,移除 MultiportExternalLBState 等 设计

robertgshaw2-redhat 认为状态类过于复杂,建议简化。

结论:最终版本移除了这些类,使用简单变量。 · 已解决

添加探针重试机制和配置参数 测试

robertgshaw2-redhat 要求增加探针重试机制,并添加可配置参数(间隔、超时、失败阈值),并添加测试模拟故障。

结论:作者添加了 probe_interval 等配置,并编写了测试。 · 已解决

使用 PR_SET_PDEATHSIG 确保子进程退出 正确性

njhill 建议设置 PDEATHSIG 使 supervisor 死亡时自动通知子进程。

结论:未在最终代码中观察到该变更,可能未采纳。 · unresolved

风险与影响

  • 进程管理:supervisor 负责子进程的 fork、信号转发和退出等待。若 supervisor 异常崩溃,子进程可能成为孤儿(因未设置 PDEATHSIG)。
  • 健康探测:通过 HTTP 探测子进程状态,网络延迟或端口竞争可能导致误判。默认探测间隔 5s、超时 5s、失败阈值 3 可在部分场景调整。
  • 兼容性:此模式默认不启用,不影响现有 DP 模式。限制不支持 gRPC、UDS、HTTPS、api-server-count>1,需在文档中说明。
  • 测试覆盖:单元测试和模拟集成测试覆盖了主要逻辑,但未在真实多 GPU 集群中验证。

对用户:提供新的 K8s 友好部署选项,简化 D-并行部署流程。对系统:增加 supervisor 进程开销。对团队:需要维护新增的 supervisor 逻辑和探针配置。

进程管理复杂度 健康探测网络依赖 PDEATHSIG 未设置 测试覆盖真实 GPU

关联 Issue

#40814 [Feature]: Support a node-local external DP mode with a single `vllm serve` and aggregated admin health endpoint

完整报告

参与讨论