Pull Request已成功合入, 合并人@tobking
(感谢 jason lyu 的贡献)变更摘要
本 PR 对 Motor 的 FaultReporter 进行了重大重构,将引擎故障感知机制从 ZMQ SUB 订阅全面迁移到 HTTP 轮询 vLLM FT 框架的 GET /fault_tolerance/status 接口,并新增 Controller 侧软件故障(ENGINE_DEAD/ENGINE_UNHEALTHY)的统一 Token 重推恢复策略,实现软硬件 L2 故障的闭环自动修复。
主要改动
-
FaultReporter 从 ZMQ 订阅改为 HTTP 轮询:
motor/node_manager/core/fault_reporter.py移除了zmq、msgspec.msgpack依赖,新增query_engine_ft_status()调用以轮询每个 endpoint 的GET /fault_tolerance/status;引入_STARTUP_GRACE_SEC(300s)冷启动宽限期防误报、max_poll_failures连续失败阈值判定 dead,去重 key 由 payload engine id 统一为受管 endpoint id;支持通过 user config 引擎段enable-fault-tolerance/enable_fault_tolerance自动启用(_engine_ft_enabled()) -
L2 故障策略拆分为软硬件 selector 注册表:
motor/controller/fault_tolerance/strategy/strategy.py将level2_strategy拆分为_L2_STRATEGY_SELECTORS元组,含_select_software_fault_strategy(仅对 ACTIVE 实例启动,INACTIVE/DELETED 由心跳机制处理)和_select_hardware_fault_strategy,二者统一返回TokenReinferenceStrategy;StrategyBase独立至strategy/base.py以消除循环 import -
TokenReinferenceStrategy 实现循环驱动恢复:
motor/controller/fault_tolerance/strategy/token_reinference.py新增完整的execute()循环逻辑——锁内快照实例的node_managers/endpoints,通过NodeManagerApiClient.apply_engine_recovery()下发 vLLM FTretry命令,聚合引擎状态直至全部healthy结束;连续空轮(_MAX_EMPTY_ROUNDS=3)放弃防无限循环,stop()通过event.set()可中断 -
新增 POST /node-manager/engine-recover 路由:
motor/node_manager/api_server/node_manager_api.py新增engine_recover端点,接收{"commands": [{"endpoint_id", "instruction", "params"}]},逐条调用apply_engine_ft_command()转发至引擎POST /fault_tolerance/apply,单命令失败隔离、endpoint_id拒绝 bool 类型(True == 1陷阱)、body 非对象返回 400 -
引擎 FT 协议层收敛为共享模块:新增
motor/common/http/engine_ft_client.py提供query_engine_ft_status()和apply_engine_ft_command(),healthy 引擎不重复下发命令、状态按 engine id 精确匹配;motor/common/constants.py新增FT_STATUS_PATH、FT_APPLY_PATH、ENGINE_RECOVER_PATH等协议常量;配置字段zmq_pub_port删除,新增poll_interval_sec(5.0)/poll_timeout_sec(5.0)/max_poll_failures(3)


代码审查
The documentation searches reveal no dangerous instructions or configurations introduced by this diff. Now let me provide the closing summary.
审查总结
逐文件审查结果:
| 文件 | 结果 |
|---|---|
.agent/skills/motor-dev/references/controller.md |
无问题(文档引用表更新) |
.agent/skills/motor-dev/references/nodeman.md |
无问题(架构图/文件表更新) |
docs/zh/design/fault_tolerance/fault_manager.md |
无问题(设计文档更新) |
docs/zh/developer_guide/components/controller.md |
无问题(策略文档更新) |
docs/zh/developer_guide/components/node_manager.md |
无问题(API/配置文档更新) |
examples/features/config_sample.json |
无问题(JSON key 正确,字段替换正确) |
motor/common/constants.py |
无问题(新增 FT 常量,__all__ 更新正确) |
motor/common/http/engine_ft_client.py |
无问题(新增共享 FT HTTP 客户端,逻辑正确) |
motor/config/node_manager.py |
无问题(zmq_pub_port → poll_* 字段替换正确) |
motor/controller/api_client/node_manager_api_client.py |
无问题(新增 apply_engine_recovery,异常安全) |
motor/controller/fault_tolerance/strategy/__init__.py |
无问题(StrategyBase 移入 base.py,消除循环 import) |
motor/controller/fault_tolerance/strategy/base.py |
无问题(新增独立基类模块) |
motor/controller/fault_tolerance/strategy/scale_p2d.py |
无问题(import 路径更新) |
motor/controller/fault_tolerance/strategy/strategy.py |
无问题(L2 策略 selector 注册表,软件/硬件故障统一返回 TokenReinferenceStrategy) |
motor/controller/fault_tolerance/strategy/token_reinference.py |
无问题(循环驱动实现正确,锁内快照 + event 可中断) |
motor/node_manager/api_server/node_manager_api.py |
无问题(新增 engine_recover 路由,参数校验完善) |
motor/node_manager/core/fault_reporter.py |
1 个 P3 问题(硬编码 "unhealthy" 替代已导入常量) |
tests/controller/fault_tolerance/strategy/test_strategy.py |
无问题(测试覆盖软件故障 selector ACTIVE gate) |
tests/controller/fault_tolerance/strategy/test_token_reinference.py |
无问题(测试覆盖循环驱动所有路径) |
tests/node_manager/api_server/test_node_manager_api_engine_recover.py |
无问题(测试覆盖路由校验/转发/隔离) |
tests/node_manager/core/test_fault_reporter.py |
无问题(测试覆盖轮询/去重/冷启动宽限期/malformed payload) |
按优先级统计:P0: 0, P1: 0, P2: 0, P3: 1
整体风险判断:低风险。此次变更代码逻辑正确,异常处理完善(poll 失败不杀线程、malformed payload 不崩溃、HTTP 调用有 finally 清理、stop/start 防双线程),测试覆盖充分(863 passed)。唯一的 P3 问题是 fault_reporter.py:287 行使用了硬编码字符串 "unhealthy" 而非已导入的 ENGINE_STATUS_UNHEALTHY 常量,当前运行时行为等价,属于可维护性改进项。
| 类型 | 数量 |
|---|---|
| 🔴 阻塞 | 0 |
| 🟡 建议 | 1 |
💬 仅评论


- ❌ PR 新增代码 1757 行超过 1000 行,且标题未标注"反合"
请修正后重新提交,或联系仓库管理员。


1. 合入背景
vLLM FaultTolerance 框架(vllm-project/vllm#44428)最终实现不再通过 ZMQ 广播引擎故障状态,改为外部轮询 REST 接口(
GET /fault_tolerance/status)。Motor 侧 FaultReporter 仍基于旧版 ZMQ 设计将无法感知引擎故障。本 PR 将 FaultReporter 重构为 HTTP 轮询模式并上报软件故障。关联 ISSUE:#448
2. 修改内容
motor/node_manager/core/fault_reporter.py):GET /fault_tolerance/status(business_port)max_poll_failures次按 dead 上报;_STARTUP_GRACE_SEC(300s)冷启动宽限期防误报;去重 key 统一为受管 endpoint id(多 endpoint 不互相覆盖);状态解析异常不杀死轮询线程enable-fault-tolerance/enable_fault_tolerance为 true 或 1),无需 NodeManager 显式配置motor/common/constants.py+motor/common/http/engine_ft_client.py):FT 状态路径/状态词/超时协议常量收敛为共享模块,query_engine_ft_status为 FaultReporter 状态轮询入口zmq_pub_port删除,新增poll_interval_sec(5.0)/poll_timeout_sec(5.0)/max_poll_failures(3)3. 资料变更
涉及,同步更新:
docs/zh/developer_guide/components/node_manager.md:软件故障上报章节(轮询模式 + 自动启用)、配置表docs/zh/design/fault_tolerance/fault_manager.md:FaultReporter 架构与上报链路(HTTP 轮询)、NodeManager 侧配置表examples/features/config_sample.json:NodeManager 段 fault_tolerance_config 字段同步4. 接口变更
涉及(NodeManager 管理面接口):
fault_tolerance_config.zmq_pub_port,新增poll_interval_sec/poll_timeout_sec/max_poll_failures5. 测试结果
单测(
bash tests/run_tests.sh tests/controller/ tests/node_manager/ tests/config/):839 passed新增/重写测试覆盖:
1值检测、非引擎段忽略(14 项)静态检查:pylint / ruff 通过
6. CheckList