Prhub

#1989 Add a skeleton RayWorkerManager and a wiring entry point

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

执行摘要

引入 `RayWorkerManager` 骨架与工作器规格入口,为统一工作器生命周期管理奠基。

本 PR 是对 Issue #1837 "Tracking issue for refactoring and enhancements" 的响应。其核心动机在于构建一个统一的工作器管理抽象层 (RayWorkerManager),以解耦并集中管理不同类型的 Ray 工作者(如路由器、会话服务器、推理引擎)的启动、寻址与生命周期,为后续移除硬编码、支持新的部署模式(如 Kubernetes 原生模式)以及实现更灵活的资源管理(如动态端口分配)奠定架构基础。PR body 明确指出这是重构链的一环。

本 PR 值得相关架构团队和负责 Rollout 模块的工程师精读。它不是一个功能性的变更,而是一个重要的架构基础搭建。建议关注:

  1. 抽象设计:RayWorkerManager 作为单一管理器的设计,以及通过 specs 模块聚合不同工作器规格的模式,是后续所有工作器管理重构的基石。
  2. 重构路径:理解 wiring.py 如何将启动流程从三个训练入口中抽取出来,这为未来支持非 Ray 部署模式(如注释中提到的 Kubernetes)预留了扩展点。
  3. TODO 规划:仔细阅读代码中的 TODO 注释,它们清晰地指出了当前实现的差距和下一步的演进方向。
    对于普通贡献者,了解此 PR 的作用即可,无需深入细节。
讨论亮点

Review 审核由 guapisolo 完成并批准。审核评论指出:"Reviewed the RayWorkerManager wiring seam introduced in #1989 through the checked stack tip at safe-merge checkpoint #2176. The remaining skeleton gaps are explicitly tracked by TODOs; no additional blockers found—LGTM." 这表明审核者认可了当前骨架结构的合理性,并认为后续的 TODO 标记足够清晰,可以作为后续 PR 的工作指引。没有发现进一步的争议或未解决的疑虑。

实现拆解

  1. 引入工作器管理骨架:在 miles/utils/workers/ray_worker_manager.py 中创建 RayWorkerManager 类。该类目前仅包含 launch(创建远程 Actor)和 instance(按名称获取 Actor)两个静态方法作为接口,核心逻辑留待后续 PR 实现。
  2. 创建工作器启动接入点:新增 miles/ray/wiring.py 文件,提供 launch_worker_manager 公共函数。该函数协调整个启动流程:调用 compute_specs 计算工作器规格,调用 create_placement_groups 分配资源,并最终调用 RayWorkerManager.launch 启动管理器 Actor。同时返回 Placement Groups 句柄,供后续组件使用。
  3. 建立工作器规格汇总机制:新增 miles/ray/specs/ 模块。其中 entrypoint.py 定义 compute_specs 函数,作为汇总各类工作器规格的单一入口;inference.py 定义了 specs_router、specs_session_server 和 specs_inference_engine 三个规格计算函数(目前返回 None)。这建立了一个声明式的工作器规格框架。
  4. 重构训练入口的资源分配:修改 train.py、train_async.py 和 train_multi_lora_async.py,将原先直接调用 create_placement_groups 获取 pgs 的逻辑,替换为调用 launch_worker_manager(args) 并接收 (_handle, pgs)。这改变了程序启动的依赖注入路径,将 WorkerManager 的启动提前到 Placement Group 分配之后。
  5. 配套文件:创建空的 miles/ray/specs/__init__.py 以使其成为 Python 包。

配套测试:本 PR 未包含直接的单元测试文件变更。这是合理的,因为主要新增的是骨架代码和接入点,真实逻辑的测试将在后续 PR(如为 RayWorkerManager 添加实际功能时)中补充。

文件 模块 状态 重要度
miles/utils/workers/ray_worker_manager.py 工作器管理 added 7.92
miles/ray/wiring.py 接线入口 added 7.52
miles/ray/specs/inference.py 工作器规格 added 7.21
train.py 训练入口 modified 5.75

关键符号

RayWorkerManager.launch RayWorkerManager.instance launch_worker_manager compute_specs specs_router specs_session_server specs_inference_engine

关键源码片段

miles/utils/workers/ray_worker_manager.py core-logic

核心新文件,定义了未来统一管理工作器生命周期的 `RayWorkerManager` 骨架类,是本次重构引入的关键抽象。

import ray
​
# TODO: unique name, maybe with args.run_uuid
_ACTOR_NAME = "ray_worker_manager"
​
​
class RayWorkerManager:
    @staticmethod
    def launch(args, specs, pgs):
        """启动一个远程的 WorkerManager Actor。
        当前为骨架实现,仅创建并返回 Actor 句柄。
        TODO: 实现实际的 Actor 逻辑,用于管理 specs 中定义的工作器。"""
        return ray.remote(RayWorkerManager).options(name=_ACTOR_NAME).remote()
​
    @staticmethod
    def instance() -> ray.actor.ActorHandle:
        """获取已存在的、通过名称注册的 WorkerManager Actor。"""
        return ray.get_actor(_ACTOR_NAME)
​
    # TODO: implement ( 例如 start_workers, stop_workers, get_worker_addresses 等方法 )
miles/ray/wiring.py core-logic

核心新文件,提供了启动 WorkerManager 和分配资源的公共入口函数 `launch_worker_manager`,是连接训练入口与新架构的接入点。

from miles.ray.placement_group import create_placement_groups
from miles.ray.specs.entrypoint import compute_specs
from miles.utils.workers.ray_worker_manager import RayWorkerManager
​
​
def launch_worker_manager(args):
    """启动工作器管理器的公共入口。
    TODO: 在 K8s 原生模式下提前返回。"""
    return _launch_ray_worker_manager(args)
​
​
def _launch_ray_worker_manager(args):
    """内部实现:计算规格 -> 分配资源 -> 启动管理器。"""
    specs = compute_specs(args) # TODO: 后续应传递 specs 而非 args 给 WorkerManager
    pgs = create_placement_groups(args) # TODO: 后续应由 WorkerManager 内部管理 pgs
    handle = RayWorkerManager.launch(args, specs, pgs)
    # TODO: 禁止外部代码直接获取 pgs,应通过 WorkerManager 提供的接口访问
    return handle, pgs

评论区精华

骨架代码合并审批 other

审核者 guapisolo 确认了骨架结构和 TODO 标记的清晰性,认为在安全合并检查点后可以合并,没有发现阻塞问题。

结论:骨架代码结构被认可,后续实现由 TODO 跟踪。 · 已解决

风险与影响

  1. 集成风险:虽然本 PR 变更了训练入口的启动流程,但由于 RayWorkerManager 和 wiring 模块均为骨架代码,且 compute_specs 返回空列表,其行为与旧流程在功能上基本等价(pgs 仍被正确返回)。因此,短期内引入回归的风险较低。
  2. 架构风险:引入新的间接层(wiring -> specs -> RayWorkerManager)增加了代码的复杂度。如果后续实现未能严格遵循此模式,或 TODO 项长期未完成,可能导致架构腐化。目前 launch 方法接收 args, specs, pgs 但未使用(TODO: pass in specs instead of args),以及 wiring 函数直接暴露 pgs(TODO: forbid code outside RayWorkerManager to know pg),是潜在的临时耦合点。
  3. 可测试性:当前骨架代码缺乏单元测试覆盖,主要风险在于接口签名(如 launch 的参数)在后续实现中可能发生改变,导致现有调用点需要同步修改。但鉴于这是重构的初期阶段,且调用点有限,此风险可控。

对用户/系统:本 PR 本身不引入面向用户的特性或行为变更。它是一个纯粹的内部架构重构,旨在为系统带来更好的模块化和可维护性。短期内,系统行为应保持不变。
对团队:本 PR 建立了未来工作器管理的核心抽象,将引导后续多个 PR(如参考历史 PR 分析中看到的 2049, 2048, 2006 等)的开发方向。它明确了资源分配(Placement Groups)、规格计算(Specs)和生命周期管理(WorkerManager)的职责边界,有助于团队并行开发不同类型的工器器。

架构过渡期耦合 骨架代码无测试覆盖

关联 Issue

#1837 Tracking issue for refactoring and enhancements

完整报告

参与讨论