Skip to content

fix(pd): route DP logical workers via base endpoint - #1522

Merged
lightseek-bot merged 1 commit into
smg-project:mainfrom
aurickq:aurick/pd-dp-aware-endpoint-url
May 23, 2026
Merged

lightseek-bot merged 1 commit into
smg-project:mainfrom
aurickq:aurick/pd-dp-aware-endpoint-url

Conversation

@aurickq

@aurickq aurickq commented May 23, 2026

Copy link
Copy Markdown
Contributor

Description

Problem

HTTP PD disaggregation can fail when routing to DP-aware logical workers. In that configuration, SMG represents each logical DP worker with a URL suffix such as http://host:port@rank. The HTTP PD router used that logical URL as the network request target, so URL parsing treated the value after @ as the host. This can surface as 502 responses with errors like:

  • PD disaggregation request failed
  • PD request transport error
  • error sending request for url (http://0.0.0.0/generate)

This affects HTTP PD disaggregation configurations where DP-aware worker discovery or explicit DP worker registration creates logical workers with @rank URLs.

Solution

Use the worker endpoint URL for actual HTTP dispatch. For DP-aware logical workers, endpoint_url() uses the worker's dp_base_url, while preserving the logical worker URL for identity and selection.

The PD router now also propagates selected DP ranks into the prefill and decode request bodies so the backend receives the selected logical ranks after dispatch goes to the base endpoint.

Changes

  • Build PD prefill/decode HTTP requests from worker.endpoint_url(route) instead of the logical worker URL.
  • Inject routed_dp_rank for selected prefill and decode workers when DP rank metadata is present.
  • Inject disagg_prefill_dp_rank into decode requests when the selected prefill worker has DP rank metadata.
  • Add a regression test that verifies a logical URL like http://127.0.0.1:30000@2 dispatches to http://127.0.0.1:30000/generate.

Test Plan

  • cargo +nightly fmt --all --check
  • cargo test -p smg test_build_post_uses_dp_base_url_for_logical_worker
  • Manual HTTP PD + DP-aware worker smoke test: before this change, requests failed with a transport error targeting http://0.0.0.0/generate; after this change, requests completed successfully and gateway logs showed selected DP ranks being propagated.
Checklist
  • cargo +nightly fmt passes
  • cargo clippy --all-targets --all-features -- -D warnings passes
  • (Optional) Documentation updated
  • (Optional) Please join us on Slack #sig-smg to discuss, review, and merge PRs

Summary by CodeRabbit

  • Improvements

    • Enhanced data placement rank metadata routing through the proxy with more selective computation and injection based on available ranks.
  • Refactor

    • Updated request construction to use worker endpoint URLs directly.
  • Tests

    • Added unit test to verify correct URL derivation in request handling.

Review Change Stack

Signed-off-by: Aurick Qiao <aurick@thinkingmachines.ai>
@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4e53582e-65df-4697-b236-41ac06490cab

📥 Commits

Reviewing files that changed from the base of the PR and between 12413dc and f5c9f87.

📒 Files selected for processing (1)
  • model_gateway/src/routers/http/pd_router.rs

📝 Walkthrough

Walkthrough

The PD proxy's dual-dispatch logic was refactored to compute prefill and decode DP-rank metadata independently and inject them selectively into JSON payloads. Request construction for downstream legs now uses the selected Worker instance to resolve endpoint URLs via worker.endpoint_url(route) instead of string-based api_path construction. A new unit test validates the DP base URL behavior for logical workers.

Changes

DP-rank metadata and worker-based request routing

Layer / File(s) Summary
Dual-rank variable initialization and import cleanup
model_gateway/src/routers/http/pd_router.rs
Removes unused api_path import and initializes separate prefill_rank and decode_rank as optional isize values derived from the selected worker's DP rank for later policy-based override.
DP-rank policy selection and conditional JSON injection
model_gateway/src/routers/http/pd_router.rs
Refactors rank selection logic to apply select_dp_rank independently to prefill and decode ranks, and updates JSON payload injection so routed/disaggregation rank fields are written only when the corresponding rank is present.
Worker-based endpoint URL and request builder refactoring
model_gateway/src/routers/http/pd_router.rs
Changes build_post_with_headers to accept a Worker reference and compute request destination via worker.endpoint_url(route) instead of constructing URLs from api_path. Callers updated to pass the selected Worker instance directly rather than a URL string.
Unit test for worker-based endpoint URL resolution
model_gateway/src/routers/http/pd_router.rs
New unit test test_build_post_uses_dp_base_url_for_logical_worker verifies that build_post_with_headers constructs request URLs via worker.endpoint_url() after configuring a logical worker with DP settings.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • lightseekorg/smg#1007: Both PRs modify the PD dual-dispatch flow for DP-rank handling, with the main PR's routing and injection changes directly supporting the DP-rank scheduling feature.
  • lightseekorg/smg#434: Main PR's changes to DP-rank metadata injection and worker-based endpoint_url resolution overlap with consolidation of DP-awareness into BasicWorker.

Suggested labels

tests

Suggested reviewers

  • CatherineSue
  • key4ng
  • slin1237

Poem

🐰 The ranks now split their humble ways,
Prefill and decode find their place,
While workers guide the endpoint through,
No string-built paths will interfere—
A test ensures the way is true! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(pd): route DP logical workers via base endpoint' directly summarizes the main change: fixing PD routing to use the base endpoint for DP logical workers instead of their logical URLs.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the model-gateway Model gateway crate changes label May 23, 2026
@aurickq
aurickq marked this pull request as ready for review May 23, 2026 00:03

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the PDRouter to improve the handling of data parallel (DP) ranks and updates the request construction logic to utilize the Worker trait. Specifically, it introduces explicit tracking of prefill and decode ranks and replaces the api_path utility with worker.endpoint_url. Feedback highlights a potential regression in URL path joining that could lead to double slashes and suggests verifying that the injected JSON keys for DP ranks align with external protocol specifications.

Comment on lines +391 to +409
if let Some(p_rank) = prefill_rank {
Self::inject_dp_rank_to_json(
&mut prefill_json_request,
p_rank,
"routed_dp_rank",
);
Self::inject_dp_rank_to_json(
&mut decode_json_request,
p_rank,
"disagg_prefill_dp_rank",
);
}
if let Some(d_rank) = decode_rank {
Self::inject_dp_rank_to_json(
&mut decode_json_request,
d_rank,
"routed_dp_rank",
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The PD router is injecting routed_dp_rank and disagg_prefill_dp_rank. While data_parallel_rank is the standard internal key, please verify if these names are required by the external PD disaggregation protocol. Per repository rules, alignment with external specifications takes priority over internal consistency for protocol data structures.

References
  1. For protocol data structures that mirror an external API, prioritize alignment with the external specification over internal consistency.

Comment on lines +1106 to +1107
let endpoint_url = worker.endpoint_url(route);
let mut request = client.post(endpoint_url).json(json_request);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The previous implementation used api_path(url, route), which safely handles leading/trailing slashes to avoid double slashes in the resulting URL. worker.endpoint_url(route) currently performs a simple concatenation: format!("{}{}", self.base_url(), route). Consider using api_path(worker.base_url(), route) to maintain the previous safety.

Suggested change
let endpoint_url = worker.endpoint_url(route);
let mut request = client.post(endpoint_url).json(json_request);
let endpoint_url = super::pd_types::api_path(worker.base_url(), route);
let mut request = client.post(endpoint_url).json(json_request);

@lightseek-bot
lightseek-bot merged commit 7d52c8d into smg-project:main May 23, 2026
49 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jun 11, 2026
2 tasks
Zhichenzzz added a commit to radixark/sgl-router-for-miles that referenced this pull request Jul 21, 2026
Ports smg-project/smg#1522 to this fork's dispatch path and current
sglang field names (routed_dp_rank / disagg_prefill_dp_rank).

Three related bugs in the DP-aware PD-disaggregation path, found by
forcing --router-dp-aware and exercising real per-rank worker
registration end-to-end:

- pd_router.rs dispatched requests using Worker::url(), which is a
  worker's logical "@rank" identity for DP-aware workers, not a
  dispatchable address. Dispatch now goes through endpoint_url()/
  base_url(), and decode requests are stamped with
  disagg_prefill_dp_rank so decode knows which prefill rank's KV cache
  to pull.
- DPAwareWorkerBuilder derived bootstrap_host by URL-parsing the
  "@rank"-suffixed logical url, which parses the rank as the hostname
  (e.g. "http://host:port@1" resolves host as numeric "1" ->
  0.0.0.1), breaking the decode->prefill bootstrap handshake.
  bootstrap_host is now derived from base_url instead.
- WorkerInfo (the /workers API) had no way to report a DP-aware
  worker's real address at all; added base_url and dp_rank fields.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

model-gateway Model gateway crate changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants