Skip to content

[Rust Frontend][gRPC] Separate liveness from inference readiness - #6

Draft
JulienDarve wants to merge 633 commits into
jdarve/grpc-liveness-readiness-basefrom
jdarve/grpc-liveness-readiness
Draft

JulienDarve wants to merge 633 commits into
jdarve/grpc-liveness-readiness-basefrom
jdarve/grpc-liveness-readiness

Conversation

@JulienDarve

@JulienDarve JulienDarve commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

Overview

The Rust frontend's gRPC health service reports the same status for every service name, so a Kubernetes probe or a sidecar cannot tell an engine that is paused for an RL weight update from one that must be restarted. This adds liveness and readiness health services and leaves the existing names unchanged. Motivation: ai-dynamo/dynamo#14897.

Claims

  • New liveness service: SERVING unless the engine has failed. Pause, sleep, weight updates, and orderly shutdown do not affect it until the listener closes; a prior engine failure keeps it NOT_SERVING.
  • New readiness service: NOT_SERVING while a pause, sleep (including a partial wake-up), or weight update sent through this frontend's HTTP or gRPC control APIs is in effect, and on engine failure or shutdown.
  • On shutdown, NOT_SERVING is published before the gRPC listener stops accepting connections.
  • vllm.Inference, vllm.Control, and "" behave as before. No protobuf changes.
Engine state liveness (new) readiness (new) vllm.Inference, vllm.Control, "" (unchanged)
Serving SERVING SERVING SERVING
Paused, asleep, partially awake, or weight update open SERVING NOT_SERVING SERVING
Engine failed NOT_SERVING NOT_SERVING NOT_SERVING
Orderly shutdown SERVING until the listener closes NOT_SERVING, published before the listener closes NOT_SERVING, published before the listener closes

Validation

Unit tests (run from rust/): cargo nextest run -p vllm-server -p vllm-engine-core-client -p vllm-mock-engine: 662 passed. cargo clippy -p vllm-server -p vllm-engine-core-client --tests -- -D warnings, cargo fmt --all -- --check, and pre-commit on the changed files passed. CI's existing cargo nextest run --workspace step runs the new tests.

New tests use the scripted engine in vllm_engine_core_client::mock_engine. Each fails when its behavior is reverted in the implementation:

Test Protects
grpc_pause_withdraws_readiness_only Pause makes readiness NOT_SERVING while liveness, vllm.Inference, vllm.Control, and "" stay SERVING; resume restores it
grpc_shutdown_closes_health_watch_and_server (extended) Orderly shutdown fails readiness and closes the liveness watch without a NOT_SERVING update
grpc_health_transitions_to_not_serving_when_engine_becomes_unhealthy (extended) Engine failure fails liveness and readiness too
availability_returns_only_after_full_wake_up A partial wake-up keeps the engines unavailable
cancelled_resume_confirms_availability_with_engines A cancelled call still ends with the engines' confirmed state
resume_keeps_available_engines_available An unneeded resume does not flap readiness
overlapping_pause_and_resume_confirm_with_engines Overlapping calls are confirmed with the engines instead of using the last result
weight_update_availability_follows_the_worker_session Readiness stays down through an open weight update, a full wake-up, and a failed finish, and returns after a successful finish or a failed load

Live run on 1x RTX 6000 Ada with Qwen/Qwen3-0.6B, using this branch's Rust binary (debug build) and its Python package (editable install with precompiled kernels):

VLLM_USE_FLASHINFER_SAMPLER=0 vllm-rs serve Qwen/Qwen3-0.6B --host 127.0.0.1 --port 8000 --grpc-port 50051 \
  -- --enable-sleep-mode --gpu-memory-utilization 0.5

VLLM_USE_FLASHINFER_SAMPLER=0 works around the test machine's CUDA 11.5 nvcc, which cannot JIT-compile FlashInfer's sampler. A probe script polled grpc.health.v1.Health/Check every 0.5 s on a new connection per check, as kubelet does, kept one Watch per service open, and drove vllm.Control and /v1/completions:

Step readiness liveness, vllm.Inference, vllm.Control, ""
After startup, then a completion SERVING SERVING
PauseGeneration in abort, wait, and keep modes NOT_SERVING SERVING
ResumeGeneration after each, then a completion SERVING SERVING
Sleep(level=1), then WakeUp(tags=["weights"]) NOT_SERVING SERVING (liveness and vllm.Inference checked)
Full WakeUp, then a completion SERVING SERVING
keep pause held 180 s, checked every 10 s (18 checks) NOT_SERVING throughout liveness SERVING throughout
Resume after the long pause SERVING, same instance_id, completion succeeds SERVING
SIGTERM Watch receives NOT_SERVING, then closes liveness watch closes without NOT_SERVING; vllm.Inference watch receives NOT_SERVING; new connections are refused 0.4 s later

All 27 checks passed on this revision. The kill -9 check ran on the previous revision, and this revision does not change the engine-failure path: killing the EngineCore process made the readiness watch receive NOT_SERVING and close, and new connections were refused within 50 ms. The managed-engine supervisor shut the server down before the engine client reported the failure, so probes saw the listener close rather than a liveness NOT_SERVING status; the unit test above covers the latter.

Not validated: real weight-update sessions (they need a trainer; covered by the scripted test), worker failure with TP > 1 (one GPU available), the Python-supervised vllm serve --grpc-port path, and Kubernetes probes in a cluster. No model evaluation: the change does not affect generated tokens.

Details

How readiness is derived. Every pause, sleep, resume, wake-up, and weight-update call, whether from HTTP routes or gRPC Control, goes through EngineCoreClient. The client now keeps an availability watch next to its existing health watch:

  • pause_generation and sleep make the engines unavailable before the call is sent; their success means the engines are paused.
  • wake_up reports whether every engine is fully awake, and the engine resumes scheduling exactly then (EngineCore.wake_up), so its result decides availability. A partial wake-up keeps the engines unavailable.
  • When a result does not decide the state (after resume_scheduler, a failed or cancelled call, or calls that overlapped), a background task asks every engine is_sleeping, which covers both a paused scheduler and sleeping executor memory. Until it answers, the published value is unchanged, so an unneeded resume does not flap readiness. An epoch discards answers that span a later call.
  • A weight update is open from start_weight_update until a successful finish_weight_update. A failed start or update_weights closes it, matching the workers, which abandon the update in those cases; a failed finish leaves it open.

The gRPC server maps that watch to readiness. monitor_health cancels a new withdrawn token after publishing shutdown statuses, and the listener stops accepting on that token instead of the shutdown token.

Compatibility. No wire change, and no existing health name changes behavior: vllm.Inference and vllm.Control keep meaning that their API is up, and during a pause that API still answers, with a retryable rejection or a queued request depending on the pause mode. Readiness probes and clients opt in by naming readiness. Older builds do not register liveness or readiness and answer NOT_FOUND, so probe configurations should switch with the image.

Limitations.

  • Pauses that bypass these client methods (EngineCoreClient::call_utility, the dev-mode /collective_rpc route) are not observed. The Rust frontend is the only API server for its engines, so other frontends cannot pause them.
  • A non-data-parallel engine accepts resume_scheduler while a wait-mode pause or sleep is still draining. If that pause's caller was cancelled, the late sleep can still apply after readiness is restored. This is an engine-side ordering issue; data-parallel engines reject the resume.
  • A failed is_sleeping confirmation keeps the engines unavailable until the next pause, sleep, resume, or wake-up call.
  • The lib.rs shutdown ordering is not covered by a unit test (the gRPC test harness builds its own server); the live run below checks it.
  • #60505 adds an engine-side readiness broadcast that the Rust client decodes and ignores. If it lands, the is_sleeping confirmation can switch to that broadcast.

Related work and duplicates. Checked open and merged PRs and issues on 2026-10-22 and 2026-10-23. No PR splits Rust gRPC liveness from readiness. #60505 and #59179 add Python HTTP readiness endpoints. #56886 (draft) adds a gRPC shutdown grace period without separating liveness; its grace period would sit between publishing NOT_SERVING and cancelling withdrawn. #56364 (draft RFC) splits vllm.Control into several services.

AI assistance (Claude) was used to write and review this change.


Pull Request Checklist
  • I used vLLM's /pr-checklist skill. (Mandatory for agents, optional for humans).

  • AI assistance was used during the creation of this PR.

  • Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.

  • Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.

  • Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.

  • Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.

🤖 Generated with Claude Code

@BugenZhao
BugenZhao force-pushed the jdarve/grpc-liveness-readiness branch from 21feaf4 to c7c67d8 Compare October 28, 2026 11:46
qianlihuang and others added 29 commits October 29, 2026 20:51
…ject#61777)

Signed-off-by: qianlihuang <yiliu.dong@qq.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
… version (vllm-project#58468)

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
…nel FP8 weights (vllm-project#60163)

Signed-off-by: wenfei qi <ms1419344875@outlook.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
…-project#63218)

Signed-off-by: Jeremy Bottleson <jbottleson@nvidia.com>
Signed-off-by: jbottleson-nvidia <jbottleson@nvidia.com>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Co-authored-by: vllm-agent <claw@inferact.ai>
…ct#63585)

Signed-off-by: Yuanheng <jonathan.zhaoyh@gmail.com>
Co-authored-by: codex <codex@openai.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
Co-authored-by: Isotr0py <Isotr0py@outlook.com>
…re mistral-common 1.13.0 (vllm-project#64169)

Signed-off-by: Julien Denize <40604584+juliendenize@users.noreply.github.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
…ct#64481)

Signed-off-by: namgyu-youn <namgyu.dev@gmail.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
…fore graph capture (vllm-project#64423)

Signed-off-by: Andreas Karatzas <akaratza@amd.com>
…ending (vllm-project#64501)

Signed-off-by: Liran Schour <lirans@il.ibm.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
… request that finished with an error (vllm-project#63937)

Signed-off-by: Sohom Chakraborty <16609933+sohom-cs@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
…s config (vllm-project#64506)

Signed-off-by: Roi Koren <roik@nvidia.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…revert vllm-project#42129) (vllm-project#64279)

Signed-off-by: Eric Schreiber <eric.schreiber@aleph-alpha-research.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…tream (vllm-project#64425)

Signed-off-by: Thien Tran <gau.nernst@yahoo.com.sg>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Alexandre Milesi <milesial@users.noreply.github.com>
Signed-off-by: milesial <milesial@users.noreply.github.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
…m-project#64251)

Signed-off-by: Liran Schour <lirans@il.ibm.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
…entally (vllm-project#58780)

Signed-off-by: Eugenio "Jay" Zuccarelli <11176606+jayzuccarelli@users.noreply.github.com>
Signed-off-by: Ben Browning <56071+bbrowning@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Ben Browning <56071+bbrowning@users.noreply.github.com>
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…try is unavailable (vllm-project#63788)

Signed-off-by: Sungsoo Ha <sungsooh@nvidia.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
… cuts the offload hit (vllm-project#63566)

Signed-off-by: Kaloyan Naumov <knaumov@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
Signed-off-by: NickLucche <nicolo.lucchesi@mistral.ai>
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
Co-authored-by: Matthew Bonanni <mbonanni@redhat.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ject#64113)

Signed-off-by: NickLucche <nicolo.lucchesi@mistral.ai>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
Co-authored-by: vllm-agent <claw@inferact.ai>
…project#62930)

Signed-off-by: Javier López <59578422+javieratomic@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Itay Etelis <92247226+Etelis@users.noreply.github.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
…t#64019)

Signed-off-by: Jakub Zakrzewski <jzakrzewski@nvidia.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Taneem Ibrahim <taneem.ibrahim@gmail.com>
Signed-off-by: Jakub Zakrzewski <jzakrzewski@nvidia.com>
Signed-off-by: Brandon Pelfrey <bpelfrey@nvidia.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
Co-authored-by: Brandon Pelfrey <bpelfrey@nvidia.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Alberto Perdomo <aperdomo@redhat.com>
Signed-off-by: alberto <aperdomo@redhat.com>
Co-authored-by: Or Ozeri <or@ozery.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
Signed-off-by: Sohom Chakraborty <16609933+sohom-cs@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
esmeetu and others added 30 commits November 2, 2026 11:10
…llm-project#65044)

Signed-off-by: esmeetu <jasonailu87@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
…peer bases late (vllm-project#63892)

Signed-off-by: Oxana Korzh <okorzh@amd.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Shanshan Shen <467638484@qq.com>
Signed-off-by: Nick Hill <nickhill123@gmail.com>
Co-authored-by: Zhuohan Li <zhuohan123@gmail.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…hem as valid JSON (vllm-project#63992)

Signed-off-by: saifltr <bagmarusaif@gmail.com>
Co-authored-by: Si Chen <62344747+cs-fisha@users.noreply.github.com>
Co-authored-by: Chauncey <chaunceyjiang@gmail.com>
…lm-project#61764)

Signed-off-by: Tianyu Guo <guoty@inferact.ai>
Co-authored-by: vllm-agent <claw@inferact.ai>
…teps on MI355X (--monokernel) (vllm-project#63440)

Signed-off-by: Aliasger Zaidy <aliasger.zaidy@amd.com>
Signed-off-by: Fangzhou Ai <31551580+Fangzhou-Ai@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Fangzhou Ai <31551580+Fangzhou-Ai@users.noreply.github.com>
…#64852)

Signed-off-by: Thien Tran <gau.nernst@yahoo.com.sg>
Co-authored-by: Kimi Code <noreply@moonshot.cn>
Co-authored-by: vllm-agent <claw@inferact.ai>
…oject#64181)

Signed-off-by: Thang Nguyen <thangnguyenvn647@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…lm-project#64355)

Signed-off-by: Thang Nguyen <thangnguyenvn647@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…n automatic sharding (22 jobs) (vllm-project#64594)

Signed-off-by: Thang Nguyen <thangnguyenvn647@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…tic sharding (17 jobs) (vllm-project#64597)

Signed-off-by: Thang Nguyen <thangnguyenvn647@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ic sharding (4 jobs) (vllm-project#64598)

Signed-off-by: Thang Nguyen <thangnguyenvn647@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…bs in automatic sharding (6 jobs) (vllm-project#64599)

Signed-off-by: Thang Nguyen <thangnguyenvn647@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…64179)

Signed-off-by: vllmellm <vllm.ellm@embeddedllm.com>
…e-AR loads, tagged x rows (vllm-project#64029)

Signed-off-by: seungrokj <seungrok.jung@amd.com>
Signed-off-by: hyukjlee <hyukjlee@amd.com>
Co-authored-by: seungrokj <seungrok.jung@amd.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
…g hooks (vllm-project#65080)

Signed-off-by: Alex-Wengg <hanweng9@gmail.com>
…llm-project#64585)

Signed-off-by: Erez Zarum <erezz@amazon.com>
Co-authored-by: Artem Perevedentsev <aperevedents@nvidia.com>
…ncelled (vllm-project#64265)

Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
…ithout the developer role (vllm-project#63901)

Signed-off-by: Francisco Javier Arceo <4163062+franciscojavierarceo@users.noreply.github.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
…es (vllm-project#63974)

Signed-off-by: Luyi Xiao <81631911+luyixiao95@users.noreply.github.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: OpenAI Codex <noreply@openai.com>
Co-authored-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Resolve conflicts after vllm-project#64265 was squash-merged to main:

- gpu_worker.py: keep main's finish_weight_update (try/finally around
  the engine finish, _end_weight_update, KV cache loan release, direct
  reload handling) and clear the incomplete-weight mark only after
  _end_weight_update(refresh=True) returns, so a failed finish or a
  failed draft head restore still reports incomplete weights.
- Test helpers: initialize both _incomplete_weight_updates and main's
  KV cache loan fields.
- Rust engine-core-client: keep the readiness guard parameter on
  call_utility and is_inference_ready on top of the squashed vllm-project#64265;
  take main's test_utils import list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJckCCukQgyfESDciCFndy
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
…tion prefix (vllm-project#58618)

Signed-off-by: Yuting Wu (DLAlgo) <yutwu@nvidia.com>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
…untime (vllm-project#64294)

Signed-off-by: reidliu41 <reid201711@gmail.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
…llm-project#63137)

Signed-off-by: world-executed <yolohalo@163.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: world-executed <yolohalo@163.com>
Co-authored-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: vllm-agent <claw@inferact.ai>
)

Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.