Prhub

#1999 Implement a worker spec for the session server

原始 PR 作者 fzyzcjy 合并时间 2026-09-04 13:45 文件变更 7 提交数 1 评论 2 代码增减 +161 / -71

执行摘要

为会话服务器实现工作者规范,统一其启动逻辑与路由器,是 Rollout 模块规范化重构的一部分。

作为 Issue #1837 “Tracking issue for refactoring and enhancements” 的一部分,目标是重构和增强系统。具体到本 PR,动机是延续 PR#2006 等已合入的重构,将相同的“工作者规范”(Worker Spec)抽象应用于会话服务器(Session Server),以消除分散在 router_manager.py 中的内联启动逻辑,提高代码的可维护性和一致性,为更复杂的 K8s 部署和异步场景做准备。

该 PR 值得精读,因为它展示了 Miles 项目在 Rollout 模块重构中采用的一个核心设计模式——通过 CommandWorkerSpec 统一描述和启动不同的工作进程。实现细节清晰,步骤完整,并包含了防止循环依赖的防御性测试。评审者的命名建议 (spec_addrs -> pool_addrs) 非常中肯,值得关注该字段在后续 PR 中是否被重命名,以保持代码库一致性。这是一个高质量的、承前启后的重构 PR。

讨论亮点

在 miles/utils/workers/worker_spec.py 的 LaunchCommandContext 类中,新增的 spec_addrs 字段命名引发了讨论。评审者 guapisolo 指出,该字段的键实际上是“池 ID”(pool ID),例如 compute_router_pool_id(0),而非“规范”(spec),当前命名 spec_addrs 可能与项目约定(如 .claude/rules/pool-cell-worker-names.md)冲突,建议重命名为 pool_addrs 或 pool_id_to_addrs 以更准确反映其用途。这是一个关于命名准确性的设计讨论,旨在维护代码库的一致性。该讨论在线程中被提出,但未看到解决结论。

实现拆解

  1. 增强启动上下文模型:在 miles/utils/workers/worker_spec.py 中,引入 HostAndPort 数据模型替代原来的 host 和 ports 字段,并扩展 LaunchCommandContext 以包含 cell_index(单元索引)、self_addrs(自身地址)和 spec_addrs(其他规范的地址,例如路由器地址)。这样,工作者在构建启动命令时能获得更完整的环境信息。

  2. 实现会话服务器规范:在 miles/ray/specs/inference.py 中,将占位函数 specs_session_server 重构为具体的 spec_session_server。该函数返回一个 CommandWorkerSpec,其中定义了名称、端口信息、调度规格(使用 compute_num_session_server_ports 计算单元数量)和启动命令。启动命令的构建逻辑被封装在内部闭包 _compute_launch_command 中,它利用新的 LaunchCommandContext 生成正确的启动参数。

  3. 简化启动逻辑并解除耦合:修改 miles/ray/rollout/router_manager.py 中的 start_session_server 函数,使其不再内联构建启动命令,而是调用 spec_session_server 返回的规范对象来生成。同时,删除了 router_manager 中不再需要的 _resolve_session_server_ports 函数,端口解析逻辑被移至新的 miles.rollout.session.ports 模块(由测试代码导入可推知)。start_router 函数也同步更新,使用新的 LaunchCommandContext 结构。

  4. 更新入口点和验证导入安全:miles/ray/specs/entrypoint.py 中的 compute_specs 函数从解包 specs_session_server 改为直接使用 spec_session_server。此外,新增了 tests/fast/ray/test_import_cycles.py 测试,确保 miles.ray.specs.inference 和 miles.ray.rollout.router_manager 这两个因重构而相互导入的模块不会产生循环依赖。

  5. 测试与文档配套:更新了 tests/fast/ray/rollout/test_router_manager.py 中的测试用例,使其导入并测试新的 resolve_session_server_ports 函数(来自 miles.rollout.session.ports),并为 start_session_server 添加了针对无效 worker 数量的验证测试。同时,更新了 docs/user-guide/cli-reference.md 中对 --session-server-workers 参数的说明。

文件 模块 状态 重要度
miles/ray/specs/inference.py 规范层 modified 8.16
miles/ray/rollout/router_manager.py 启动管理 modified 7.43
miles/utils/workers/worker_spec.py 工作者基础 modified 7.07
tests/fast/ray/test_import_cycles.py 导入安全 added 6.17
miles/ray/specs/entrypoint.py 规范入口 modified 4.32

关键符号

spec_session_server compute_session_server_instance_id LaunchCommandContext HostAndPort.addr

关键源码片段

miles/ray/specs/inference.py core-logic

核心变更文件,将占位函数 `specs_session_server` 实现为完整的 `spec_session_server` 函数,定义了会话服务器的工作者规范。

# 实现会话服务器的工作者规范
# 返回单个 CommandWorkerSpec 对象,定义其名称、端口、调度和启动命令
def spec_session_server(args) -> CommandWorkerSpec:
    _config = resolve_sglang_config(args) # TODO avoid resolve repeatedly
    interpreter_prefix = python_argv_prefix()
​
    # 启动命令构建闭包
    # 利用新的 LaunchCommandContext 获取自身地址和路由器地址
    def _compute_launch_command(ctx: LaunchCommandContext) -> str:
        config = compute_session_server_config(
            args,
            host=ctx.self_addrs["primary"].host,
            port=ctx.self_addrs["primary"].port,
            # TODO: make the indexing it k8s native compatible
            instance_id=compute_session_server_instance_id(args, ctx.cell_index),
            backend_url=ctx.spec_addrs[compute_router_pool_id(0)][0]["primary"].addr,
        )
        launch_argv = [*interpreter_prefix, "-m", "miles.rollout.session.server", *config_to_argv(config)]
        return shlex.join(launch_argv)
​
    return CommandWorkerSpec(
        name="session-server",
        port_infos=[
            PortInfo(name="primary", static_port=8000, allow_dynamic=True),
        ],
        env_var=lambda: {},
        scheduling=SchedulingSpec(
            num_cells=compute_num_session_server_ports(args),
            num_workers_per_cell=1,
            num_gpus_per_worker=0,
        ),
        launch_command=_compute_launch_command,
    )
​
# 生成唯一的实例 ID,用于多实例场景
def compute_session_server_instance_id(args, instance_index: int) -> str:
    return f"{args.run_uuid}-{instance_index}"
miles/utils/workers/worker_spec.py data-contract

基础数据模型文件,定义了本次重构的核心数据结构 `HostAndPort` 和 `LaunchCommandContext`,为所有工作者规范提供基础。

# 表示一个带协议的主机和端点地址
class HostAndPort(FrozenStrictBaseModel):
    host: str
    port: int
​
    @property
    def addr(self):
        # 自动生成 http:// 格式的地址字符串
        return f"http://{self.host}:{self.port}"
​
# dict key: name
NamedHostAndPorts = dict[str, HostAndPort]
​
​
# 工作者启动命令的上下文信息,供 spec 的 launch_command 函数使用
class LaunchCommandContext(FrozenStrictBaseModel):
    cell_index: int # 当前实例的单元索引(例如,在多个会话服务器实例中为 0,1,2...)
    self_addrs: NamedHostAndPorts # 当前工作者自身的地址(例如, primary 端口地址)
    # 其他相关工作者规范的地址映射(键为池 ID,值为该池的所有实例地址)
    # 例如,对于会话服务器,这里可以包含路由器的地址
    spec_addrs: dict[str, list[NamedHostAndPorts]]

评论区精华

`LaunchCommandContext.spec_addrs` 字段命名准确性 设计

评审者 **guapisolo** 指出,`LaunchCommandContext` 中的 `spec_addrs` 字段,其键实际上是工作者的池 ID (pool ID)(如 `compute_router_pool_id(0)`),而非规范 (spec)。当前命名 `spec_addrs` 与项目约定(`.claude/rules/pool-cell-worker-names.md`)存在冲突,建议重命名为 `pool_addrs` 或 `pool_id_to_addrs`。

结论:评审者提出了明确的重命名建议和理由,并指出在截至评论时,后续 PR 尚未修复此命名问题。 · 未解决

风险与影响

  1. 命名不一致风险:LaunchCommandContext.spec_addrs 字段的命名(“spec”)与其实际存储的内容(按池 ID 索引的地址映射)存在语义差异。如评审者所指出,这可能与项目已有的命名约定(pool-cell-worker)产生混淆,增加后续开发者理解成本,或在未来重构时引发不一致。
  2. 测试覆盖边界:新增的 test_import_cycles.py 有效验证了模块导入顺序,防止了循环依赖。然而,对于 spec_session_server 生成的启动命令的正确性,目前的测试(在 test_router_manager.py 中)是间接和基于 mock 的。缺少一个直接验证 spec_session_server 返回的 CommandWorkerSpec 对象及其 launch_command 函数在真实参数下输出正确字符串的单元测试。
  3. 重构连续性风险:本次变更删除了 router_manager._resolve_session_server_ports,并假设其逻辑已正确迁移到新模块 miles.rollout.session.ports(由测试导入推断)。如果迁移有误或新旧逻辑在某些边界情况下不一致,可能影响端口分配。当前 PR 未包含新模块的源码,其正确性依赖于后续 PR 或已有测试。

对系统:主要影响 Rollout 模块的内部结构,使会话服务器的启动逻辑与路由器等其他工作者保持一致。这提升了代码的模块化和可维护性,为后续将推理引擎纳入统一管理框架奠定了基础。对运行时行为无直接影响,属于内部重构。
对团队:为工程师提供了清晰的“工作者规范”实现范例(spec_session_server),便于未来添加新的工作者类型。LaunchCommandContext 的扩展使得工作者启动逻辑能获取更丰富的上下文,支持更复杂的部署拓扑。命名上的争议提醒团队需维护并遵循统一的术语约定。
对用户:无直接影响。这是一个纯粹的代码质量与架构改进 PR。

命名约定冲突 测试覆盖边界(启动命令正确性) 重构依赖迁移

关联 Issue

#1837 Tracking issue for refactoring and enhancements

完整报告

参与讨论