Prhub

#45300 [Rust Frontend][Bugfix] Forward --shutdown-timeout and --disable-log-stats to the managed Python engine

原始 PR 作者 wseaton 合并时间 2026-06-12 15:39 文件变更 3 提交数 1 评论 0 代码增减 +47 / -0

执行摘要

转发 --shutdown-timeout 和 --disable-log-stats 到 Python 引擎

Rust 前端托管模式下,引擎使用已知默认值导致两个关键行为异常:--shutdown-timeout 始终为 0 (abort 模式),无法优雅排空进行中的请求;--disable-log-stats 被忽略,引擎持续输出调度器统计。PR 描述提到 'The configured drain window had no effect on actual generations' 和 'managed engines silently kept stats enabled regardless of the flag',这些行为与用户期望不符。

值得合入,修复了两个明确的行为 bug。测试充分(两个新的回归测试),代码变更简洁且遵循既有模式。建议精读 into_config 方法,理解托管模式下参数转发机制,这对于 Rust 前端开发者理解系统架构有帮助。

讨论亮点

该 PR 没有 review 评论讨论。审核者 BugenZhao 直接批准,表示 LGTM。

实现拆解

  1. 修改 ManagedEngineArgs::into_config 签名(文件 rust/src/managed-engine/src/cli.rs):新增 disable_log_stats: boolshutdown_timeout: u64 参数。该方法是构建托管引擎配置的核心,之前只接收 max_model_lenlanguage_model_only
  2. into_config 中添加转发逻辑:当 disable_log_stats 为 true 时,向 python_args 追加 --disable-log-stats;当 shutdown_timeout > 0 时,追加 --shutdown-timeout 及其值(注意:timeout=0 时不转发,因为 Python 引擎默认也是 0)。
  3. 更新调用方 ServeArgs::to_managed_engine_config(文件 rust/src/cmd/src/cli.rs):从 self.runtime 中读取 disable_log_statsshutdown_timeout 字段并传递给 into_config。这个方法是实现 ServeArgsManagedEngineConfig 转换的桥梁。
  4. 添加回归测试(文件 rust/src/cmd/src/cli/tests.rs):新增两个测试函数 serve_args_forward_shutdown_timeout_to_managed_engineserve_args_forward_disable_log_stats_to_managed_engine,验证参数被正确解析并出现在 ManagedEngineConfig.python_args 中。
文件 模块 状态 重要度
rust/src/managed-engine/src/cli.rs 托管引擎 modified 6.73
rust/src/cmd/src/cli.rs CLI 入口 modified 4.32
rust/src/cmd/src/cli/tests.rs CLI 入口 modified 6.37

关键符号

ManagedEngineArgs::into_config ServeArgs::to_managed_engine_config serve_args_forward_shutdown_timeout_to_managed_engine serve_args_forward_disable_log_stats_to_managed_engine

关键源码片段

rust/src/managed-engine/src/cli.rs core-logic

核心逻辑修改:在 into_config 中新增 disable_log_stats 和 shutdown_timeout 转发。

// rust/src/managed-engine/src/cli.rs (head)impl ManagedEngineArgs {
    /// Build the managed Python - engine spawn configuration.
    pub fn into_config(
        self,
        model: String,
        max_model_len: Option<u32>,
        language_model_only: bool,
        disable_log_stats: bool, // <-- 新增 : 是否禁用日志统计
        shutdown_timeout: u64, // <-- 新增 : 优雅关闭超时秒数
        handshake_port: u16,
    ) -> ManagedEngineConfig {
        let mut python_args = self.python_args;
        // 手动转发一些参数给 Python 引擎
        if let Some(max_model_len) = max_model_len {
            python_args.push("--max-model-len".to_string());
            python_args.push(max_model_len.to_string());
        }
        if language_model_only {
            python_args.push("--language-model-only".to_string());
        }
        // 如果指定了 disable_log_stats,则转发给引擎
        if disable_log_stats {
            python_args.push("--disable-log-stats".to_string());
        }
        // 如果 shutdown_timeout > 0,则转发时间值;默认 0 表示 abort 模式,不转发
        if shutdown_timeout > 0 {
            python_args.push("--shutdown-timeout".to_string());
            python_args.push(shutdown_timeout.to_string());
        }
        if let Some(data_parallel_size_local) = self.data_parallel_size_local {
            python_args.push("--data-parallel-size-local".to_string());
            python_args.push(data_parallel_size_local.to_string());
        }        ManagedEngineConfig {
            python: self.python,
            model,
            handshake_host: self.handshake_host,
            handshake_port,
            data_parallel_size: self.data_parallel_size,
            python_args,
        }
    }
}

注意:shutdown_timeout = 0 时不转发,因为 Python 引擎默认也是 0(abort 模式),避免冗余参数。

rust/src/cmd/src/cli/tests.rs test-coverage

新增两个回归测试,验证参数转发正确性。

// rust/src/cmd/src/cli/tests.rs (head, 新增的两个测试 )#[test]
fn serve_args_forward_shutdown_timeout_to_managed_engine() {
    // 模拟用户传入 --shutdown-timeout 60
    let cli = Cli::try_parse_from([
        "vllm-rs",
        "serve",
        "Qwen/Qwen3-0.6B",
        "--shutdown-timeout",
        "60",
    ])
    .unwrap();    let Command::Serve(args) = cli.command else {
        panic!("expected serve args");
    };
    // 验证 Rust 端解析正确
    assert_eq!(args.runtime.shutdown_timeout, 60);    // 验证生成的托管引擎配置包含该参数
    let config = args.to_managed_engine_config(5555);
    assert_eq!(config.python_args, vec!["--shutdown-timeout", "60"]);
}#[test]
fn serve_args_forward_disable_log_stats_to_managed_engine() {
    // 模拟用户传入 --disable-log-stats
    let cli = Cli::try_parse_from(["vllm-rs", "serve", "Qwen/Qwen3-0.6B", "--disable-log-stats"])
        .unwrap();    let Command::Serve(args) = cli.command else {
        panic!("expected serve args");
    };
    // 验证 Rust 端解析正确
    assert!(args.runtime.disable_log_stats);    // 验证生成的托管引擎配置包含该参数
    let config = args.to_managed_engine_config(5555);
    assert_eq!(config.python_args, vec!["--disable-log-stats"]);
}

测试确保参数经过 try_parse_fromto_managed_engine_config 后正确出现在 python_args 中。

评论区精华

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

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

风险与影响

低风险:变更仅涉及托管模式下两个标志的转发逻辑,且是显式增加而非修改现有行为。测试覆盖了正向路径,但缺少单元测试验证 shutdown_timeout=0 时不转发(虽然文档已说明,但无测试断言)。冒烟的风险在于:如果 runtime.disable_log_statsruntime.shutdown_timeout 的默认值与 Python 引擎的行为不一致,可能导致意外行为。但这两个字段已在 Rust 端的 RuntimeConfig 中定义,默认值合理。

直接影响:使用 vllm-rs serve 托管模式的用户。

  • --shutdown-timeout 现在能正常优雅排空请求,避免 SIGTERM 时请求截断。
  • --disable-log-stats 现在能真正禁用引擎的调度器统计输出,减少日志噪音。
    间接影响:无。仅影响托管模式,且仅限于新增的两个标志。其他路径不受影响。
缺少边界测试(shutdown_timeout=0)

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论