已合并
[Feature] 引擎重启兜底策略:容器不重启重拉引擎 + 自杀裁决收敛 Daemon #710
jason lyu创建于 9 天前
[Feature] 引擎重启兜底策略:容器不重启重拉引擎 + 自杀裁决收敛 Daemon #710
已合并
Pull Request已成功合入, 合并人@tobking
(感谢 jason lyu 的贡献)9 天前 关联了issue:[Feature-Request|需求反馈]: 引擎重启兜底策略:容器不重启重拉引擎 + 自杀裁决收敛 Daemon
atomgit-bot
9 天前 评论:
9 天前 评论:
变更摘要
本 PR 实现了引擎进程死亡后的容器不重启兜底策略:新增 EngineRelaunchStrategy 两阶段恢复流程(先重拉引擎,失败再回退到容器重启),同时将自杀裁决权从 HeartbeatManager 收敛到 Daemon(进程生命周期管理者),并引入自杀冻结/解冻机制保护重拉窗口。EngineManager 更名为 RegisterManager 以明确职责边界,FaultReporter 从 ZMQ PUB/SUB 改为 HTTP 轮询引擎 /fault_tolerance/status 端点。
主要改动
- 新增
EngineRelaunchStrategy两阶段引擎兜底策略:Phase 1 探活全部 NodeManager → 下发POST /node-manager/engine-restart→ 轮询/node-manager/status直至全部端点 NORMAL;Phase 2 对可达 NM 发abort解冻自杀触发容器重启(motor/controller/fault_tolerance/strategy/engine_relaunch.py,333 行新增) - 新增策略失败升级链:
StrategyBase.mark_failed()标记策略失败 →InstanceMetadata.prev_strategy_failed置位 → 策略中心自动降级到EngineRelaunchStrategy(base.py新增 53 行,fault_manager.py在策略完成时记录失败标记并选择升级策略) - NodeManager 新增
POST /node-manager/engine-restart路由:支持restart(冻结自杀 →Daemon.restart_engine重拉引擎 → 重置 FaultReporter 启动宽限)和abort(解冻自杀)两种 action,并发 409、快照恢复中 409、未 start 400、pull 失败 500 且解冻(node_manager_api.py新增约 100 行) - 自杀裁决收敛到
Daemon:心跳模块退化为状态源(has_abnormal_endpoints/endpoints_generation/is_within_grace_period),Daemon新增独立 3s 仲裁线程统一裁决自杀(5×3s≈15s),并支持截止时间制freeze_suicide/unfreeze_suicide(daemon.py新增 163 行,heartbeat_manager.py删除约 39 行自杀计数逻辑) FaultReporter从 ZMQ 改为 HTTP 轮询:通过query_engine_ft_status轮询各引擎的/fault_tolerance/status端点,首次 poll 失败即冻结自杀(修复自杀 ~15s vs DEAD 上报 15-30s 时序竞态),新增reset_startup_grace方法在重拉后重置启动宽限防重拉风暴(fault_reporter.py重写,+275/-145 行)


atomgit-bot
9 天前 评论:
9 天前 评论:
9 天前 添加了label:pr-audit-failed
xiangjie10
9 天前 评论:
9 天前 评论:
🔍 PR 规范审计未通过,以下项目需要修正:
- ❌ PR 新增代码 2792 行超过 1000 行,且标题未标注"反合"
请修正后重新提交,或联系仓库管理员。


此处折叠了483条消息 查看更多
liu
3 天前 评论:
3 天前 评论:
/lgtm


tobking
3 天前 评论:
3 天前 评论:
/approve


3 天前 添加了label:approvedlgtm
3 天前 关闭了关联的issue
3 天前 合入了pull request
1. 合入背景
引擎进程死亡后,当前唯一兜底是「NodeManager 心跳 abnormal ×5(约 15s)→ 自杀 → k8s 重启 pod」,代价是全容器重建。本 PR 实现「容器不重启重拉引擎」:Controller 协同实例的所有 NodeManager 一起重拉全部引擎(rank 集合通信组一致性),重拉失败再回退到容器重启;同时把自杀裁决权收敛到 Daemon(进程生命周期管理者)。
本 PR 基于最新主线:原生引擎拉起(#698:NodeManager 直接 spawn 原生 vLLM/SGLang,删除 EngineServer 层)与 EngineServer 删除收尾(#717)均已合入,重拉链路已对接原生拉起路径。
关联 ISSUE:#472
2. 修改内容
motor/controller/fault_tolerance/strategy/engine_relaunch.py,两阶段):POST /node-manager/engine-restart→ 轮询/node-manager/status全部 NORMAL → 成功stop()被打断时 fire-and-forget 发 abort(防冻结窗口内 NM 自杀被延迟)StrategyBase.mark_failed()+InstanceMetadata.prev_strategy_failed——token 重推/UCE/弹性扩缩容等「期望引擎不重启快速恢复」的策略失败后,策略中心自动降级到 EngineRelaunchStrategy(兜底链);升级分支同样受enable_engine_relaunch门控level2_strategy挂钩:ENGINE_DEAD 软件故障直接触发 EngineRelaunchStrategy(开关关闭 → None)POST /node-manager/engine-restart(node_manager_api.py):body{"action": "restart"|"abort", "instance_id"};薄路由——restart 整体委托Daemon.restart_engine(Daemon 内部解析启动参数、冻结自杀、暂停/恢复 FaultReporter、只停引擎服务重拉不动 KV store/监控线程),路由只做 HTTP 语义映射(并发 409、快照恢复中 409、未 start 400、失败 500,零锁零状态)。部分失联协同复用既有/node-manager/stop(不在 restart 路由新加 shutdown action)daemon.py):截止时间制 freeze/unfreeze(abort 丢失自动过期,容器重启兜底永存);freeze 仅在死亡上报成功后才执行(上报失败 → Controller 不可达 → 不冻结,仲裁继续计数,容器重启兜底不被拖死);freeze 受enable_engine_relaunch门控(未开开关 → 不上报后不冻结,pod 快速自终止走 k8s 容器重启,不被 180s 冻结窗口拖延)has_abnormal_endpoints/endpoints_generation/is_within_grace_period),Daemon 独立 3s 仲裁线程统一裁决(5×3s≈15s,间隔跟随heartbeat_interval_seconds配置)+ 统一 freeze/should_suicide;冷启动误判门槛:只有「曾经 NORMAL」的 endpoint 异常才上报死亡(模型加载期不误报)_engine_ready握手事件 + Daemon 后台wait_ready——heartbeat 不再感知引擎就绪、不再 import Daemon(循环依赖解除),状态线程在探测前等待握手EngineManager→RegisterManager(register_manager.py,职责=注册/元数据管理,与 Daemon 进程管理区分)StrategyBase移至strategy/base.py(消除循环 import)enable_engine_relaunch(默认开)为「容器不重启重拉引擎」唯一开关——Controller 侧fault_tolerance_config(策略选择门控)+ NodeManager 侧fault_tolerance_config(同名配置,freeze 门控);删除MOTOR_RESTART_ENGINE环境变量及 health_check 的 SIGTERM 自杀快路径,恢复路径统一由 Daemon 按开关决策print直达容器 stdout 打印[ENGINE RELAUNCH #N]banner(容器生命周期内重拉计数 + 时间),多次重拉日志按次分区检索RuntimeStateprobe 查询(STARTING/STOPPING 保留原状态);进程组清理(start_new_session + killpg + 退出等待 + 僵尸收割);bootstrap_port字段;过时 EngineServer 提法清理3. 资料变更
涉及,同步更新:
docs/zh/developer_guide/components/node_manager.md:模块表(RegisterManager)、自杀裁决章节docs/zh/design/fault_tolerance/overview.md/fault_manager.md:策略/模块引用同步examples/features/config_sample.json:两侧 fault_tolerance_config 新字段4. 接口变更
涉及(NodeManager 管理面接口 + 配置):
POST /node-manager/engine-restart:body{"action": "restart"|"abort", "instance_id": int?},200/400/409/500/node-manager/stop语义补全为「自杀」:停引擎后延时 SIGTERM 自身(退出 -1 → k8s 重启 pod)。部分失联时 Controller 对存活 NM 复用该接口下发自杀(不再依赖引擎重拉路由)fault_tolerance_config.enable_engine_relaunch(默认 true)/engine_relaunch_complete_timeout_sec/engine_relaunch_poll_interval_sec/engine_relaunch_dispatch_retries/engine_relaunch_nm_unreachable_thresholdfault_tolerance_config.enable_engine_relaunch(默认 true,与 Controller 对齐)/engine_restart_wait_timeout_sec(180s)/engine_restart_freeze_sec(720s)MOTOR_RESTART_ENGINE环境变量(配置收敛,统一由enable_engine_relaunch决策)5. 测试结果
单测(
bash tests/run_tests.sh全量):2665 passed(rebase #698/#717 后全量基线之上)新增/重写测试覆盖:
/node-manager/stop自杀语义:停引擎 + 延时 SIGTERM 自身(pod 重启)静态检查:pylint / ruff 通过
K8s e2e(infer195,A2 跨机 EP16 = 2 pod × 8 卡):已验证通过——
e2e 定位并修复的问题:
/node-manager/stop(自杀语义)协同退出(volcano 兜底)6. CheckList