Prhub

#26245 Support DP-aware PD router dispatch

原始 PR 作者 weireweire 合并时间 2026-06-25 06:02 文件变更 3 提交数 1 评论 3 代码增减 +280 / -44

执行摘要

修复 DP-aware PD 路由的调度和 URL 问题

PDRouter selected workers but then dispatched the original JSON directly to the worker URL. In --dp-aware mode this bypassed the virtual DP worker request mutation, so prefill did not receive the chosen data_parallel_rank, decode did not know which prefill DP rank to bootstrap from, and some side paths could use the virtual http://worker@rank/ identity as a real backend URL. This made PD routing effectively worker-aware but not DP-rank-aware, and left DP-aware virtual URLs exposed to HTTP dispatch paths.

建议工程师精读该 PR,尤其是 prepare_worker_requestinject_prefill_dp_rank_for_decode 的设计,它展示了如何在不破坏现有非 DP 模式的前提下,优雅扩展 DP 感知逻辑。同时,parse_bootstrap_host_from_url 的防御式编程(fallback 为 localhost)值得学习。

讨论亮点

该 PR 由 xiaoxiaohehe001 批准,未产生额外的 review 讨论,表明变更清晰且符合预期。PR body 中提供了详尽的 A/B 验证数据,展示了 DP-aware 路由带来的显著性能提升(TTFT p50 从 4.22s 降至 1.11s,错误率从 9 降至 2)。

实现拆解

  1. 新增 PreparedWorkerRequest 结构体:封装请求目标 URL 和请求体,替代直接字符串拼接,为后续统一处理奠定基础。
  2. 引入 worker_endpoint_url 方法:通过 worker.base_url() 构建 HTTP 端点,确保 DP-aware worker 使用物理 URL 而非虚拟 url@rank
  3. 实现 prepare_worker_request 方法:对 DP-aware worker 调用 worker.prepare_request() 在请求体中注入 data_parallel_rank;非 DP 模式保持原请求不变。
  4. 增加 inject_prefill_dp_rank_for_decode 方法:在 decode 请求中插入 disagg_prefill_dp_rank 字段,传递 prefill 的 DP rank,避免 decode 端从 bootstrap_room % dp_size 猜测或调用 /query_dp_ranks
  5. 整合 prepare_pd_worker_requests 入口:组合以上逻辑,统一处理 prefill 和 decode 请求,修改原有路由调用点,确保所有请求经过正确的准备流程。
  6. 提取 parse_bootstrap_host_from_url 函数:从 worker.rs 中提取公共函数,剥离 URL 中的 @rank 后缀以解析真实的 bootstrap host;DPAwareWorker 新增 bootstrap_host 字段并存储解析结果;BasicWorkerBuilder 改用该函数,消除重复的 URL 解析代码。
文件 模块 状态 重要度
sgl-model-gateway/src/routers/http/pd_router.rs 路由层 modified 9.16
sgl-model-gateway/src/core/worker.rs 工作节点 modified 8.35
sgl-model-gateway/src/core/worker_builder.rs 工作节点 modified 6.66

关键符号

worker_endpoint_url prepare_worker_request prepare_pd_worker_requests inject_prefill_dp_rank_for_decode parse_bootstrap_host_from_url

关键源码片段

sgl-model-gateway/src/routers/http/pd_router.rs data-contract

核心路由文件,实现 DP-aware 请求准备和 rank 注入,改动最大(+203/-20)。

// 在 decode 请求中注入 prefill 的 DP rank,确保 decode 知道
// 应从哪个 DP rank 的 KV 缓存开始引导,避免回退到
// /query_dp_ranks 端点
fn inject_prefill_dp_rank_for_decode<'a>(
    decode_request: Cow<'a, Value>,
    prefill_worker: &dyn Worker,
) -> Result<Cow<'a, Value>, String> {
    // 若 prefill worker 没有 DP rank(非 DP-aware),则无需注入
    let Some(prefill_dp_rank) = prefill_worker.dp_rank() else {
        return Ok(decode_request);
    };    let mut decode_request = decode_request.into_owned();
    let Some(obj) = decode_request.as_object_mut() else {
        return Err(
            "Failed to insert disagg_prefill_dp_rank because request body is not an object"
                .to_string(),
        );
    };    // 插入 disagg_prefill_dp_rank 字段,值为 prefill 的 DP rank
    obj.insert(
        Self::DISAGG_PREFILL_DP_RANK_KEY.to_string(),
        Value::from(prefill_dp_rank as u64),
    );
    Ok(Cow::Owned(decode_request))
}
sgl-model-gateway/src/core/worker.rs data-contract

新增 parse_bootstrap_host_from_url 函数和 DPAwareWorker 的 bootstrap_host 字段,确保正确解析物理 host。

/// 从 worker URL 中解析真实的 bootstrap host,支持 dp rank 后缀(如
/// http://10.66.5.115:20664@3)和直接 URL。若 URL 格式无效则默认返回
/// "localhost"。
pub(crate) fn parse_bootstrap_host_from_url(url: &str) -> String {
    // 尝试剥离 @rank 后缀,仅当后缀可解析为整数时认为有效
    let metadata_url = match url.rsplit_once('@') {
        Some((base_url, rank)) if rank.parse::<usize>().is_ok() => base_url,
        _ => url,
    };    // 使用 url crate 解析 host,失败时添加 http:// 前缀重试,
    // 最终 fallback 为 localhost
    match url::Url::parse(metadata_url) {
        Ok(parsed) => parsed.host_str().unwrap_or("localhost").to_string(),
        Err(_) if !metadata_url.contains("://") => {
            match url::Url::parse(&format!("http://{}", metadata_url)) {
                Ok(parsed) => parsed.host_str().unwrap_or("localhost").to_string(),
                Err(_) => {
                    tracing::warn!(
                        "Failed to parse URL '{}', defaulting to localhost",
                        metadata_url
                    );
                    "localhost".to_string()
                }
            }
        }
        Err(_) => {
            tracing::warn!(
                "Failed to parse URL '{}', defaulting to localhost",
                metadata_url
            );
            "localhost".to_string()
        }
    }
}

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

  1. 核心路由路径变更PDRouter 的请求准备逻辑被替换,可能影响非 DP-aware 模式的请求流程,虽然代码在非 DP 分支保持原有行为,但需警惕回归。
  2. URL 解析依赖parse_bootstrap_host_from_url 假设 URL 中包含 @rank 后缀的格式为 ...@数字,若 future 扩展改变命名规则,可能导致错误解析。当前有 fallback 为原始 URL 的 host,不影响正确性。
  3. 缺少集成测试:虽然包含单元测试,但缺少端到端的 PD 分离部署集成测试,无法验证多 worker 场景下的完整路由链。
  4. DP-rank 兼容性:新增的 disagg_prefill_dp_rank 字段需要下游 worker 理解;若 worker 版本较旧可能忽略该字段,但仍能工作(仅回退到旧猜测逻辑)。

对用户:DP-aware 部署模式下,PD 路由将正确传递 DP rank,避免因虚拟 URL 导致的请求失败,显著降低 TTFT 并提升吞吐量(如验证所示吞吐量从 937.3 tok/s 提升至 1110.9 tok/s)。非 DP-aware 用户无感知。
对系统:消除了虚拟 url@rank 暴露为真实 HTTP 目标的安全隐患,所有 HTTP 请求均使用物理 worker URL。
对团队:代码模块化提升(提取 URL 解析函数、统一请求准备入口),降低后续维护成本。

核心路径变更 URL 解析依赖 缺少集成测试 DP-rank 兼容性

关联 Issue

#26237 Fix DP-aware PD router worker URLs

完整报告

参与讨论