健康检查管理器
健康检查管理器为 Relax 分布式训练系统提供全面的服务健康监控和自动恢复能力。它支持两种恢复策略:就地重启(针对单个服务)和全局重启(全系统重新初始化)。
概述
健康管理系统监控所有已部署的服务(Actor、Rollout、Critic、ActorFwd、Advantages 等),并在检测到故障时自动触发恢复。两种检测机制协同工作:
- 错误上报检测:服务主动上报错误(延迟约 1 秒)
- 心跳超时检测:心跳超时判定(超时阈值 120 秒)
快速开始
在训练命令中添加 --use-health-check 即可启用健康检查:
bash
python3 relax/entrypoints/train.py \
--use-health-check \
--max-global-restart 3 \
--fully-async \
...或在启动脚本中:
bash
ray job submit --address="http://127.0.0.1:8265" \
-- python3 relax/entrypoints/train.py \
--use-health-check \
--max-global-restart 3 \
...架构
组件设计
┌─────────────────────────────────────────────────────────────────┐
│ Controller (Consumer) │
│ uses: HealthManager │
│ owns: restart_serve() → in-place restart / global restart │
└────────────────────┬────────────────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────────────────┐
│ HealthManager (Coordinator Layer) │
│ Owns and coordinates internal components │
└────────────────────┬────────────────────────────────────────────┘
│
┌────────┴──────────┐
│ │
┌───────────▼──────┐ ┌────────▼────────────────┐
│ HealthStatus │ │ HealthChecker │
│ (Remote Actor) │ │ (Background Thread) │
│ │ │ │
│ Stores per-svc │ │ Periodic checking │
│ health state │ │ Unhealthy + stale │
│ │ │ detection │
└──────────────────┘ └─────────────────────────┘组件说明
| 组件 | 职责 | 实现方式 |
|---|---|---|
| ServiceHealthState | 每个服务的健康数据(健康状态、错误、心跳、步数、重启次数) | Python dataclass |
| HealthStatus | 存储和查询所有服务的健康状态 | Ray 远程 Actor |
| HealthChecker | 定期检查健康状态,检测心跳超时,触发回调 | 后台守护线程 |
| HealthManager | 协调上述组件,对外提供统一接口 | 组合包装类 |
健康状态
每个服务拥有一个 ServiceHealthState 数据类:
python
@dataclass
class ServiceHealthState:
healthy: bool = True # 当前健康状态
error: Optional[str] = None # 不健康时的错误信息
last_heartbeat: float = time.time() # 上次心跳时间戳
current_step: int = 0 # 最新上报的训练步数
task_running: bool = False # 服务任务是否正在运行
restart_count: int = 0 # 该服务的重启次数检测机制
错误上报检测
服务通过 report_error() 主动上报错误。HealthChecker 每秒轮询 get_unhealthy_services(),一旦发现异常立即触发恢复。
python
# 服务后台循环内部(如 Actor._background_run):
try:
ray.get(self.actor_model.train_fully_async(self.step))
# 成功时上报心跳
self.healthy.update_heartbeat.remote("actor", self.step + 1)
except Exception as e:
# 失败时上报错误 —— 约 1 秒内触发恢复
self.healthy.report_error.remote("actor", f"Training failed: {e}")心跳超时检测
每个服务定期发送心跳。如果超过 120 秒(HEARTBEAT_TIMEOUT)未收到心跳,则判定该服务已失联并触发恢复。
这可以捕获服务无声崩溃(没有调用 report_error())的情况。
恢复策略
两级恢复
| 条件 | 策略 | 说明 |
|---|---|---|
| Actor / Rollout / ActorFwd 故障 | 全局重启 | 完整的 Controller 销毁 + 从零重新初始化 |
| 任意角色重启次数 ≥ 3 | 全局重启 | 系统不稳定,需要全新起步 |
| 其他角色故障(如 Critic、Advantages) | 就地重启 | 复用 placement group,恢复步数,重新运行任务 |
全局重启次数超过 --max-global-restart | 终止 | os._exit(1) —— 系统无法恢复 |
全局重启
全局重启会完全销毁所有资源(Ray Serve 部署、数据系统、DCS 协调器、Ray 本身),然后通过 Controller.__init__() 从零重新初始化。
阶段一 —— 销毁:
1. 停止 HealthManager
2. 删除所有 Ray Serve 部署
3. 删除 metrics 和 DCS 部署
4. 终止数据系统 Actor
5. serve.shutdown() + ray.shutdown()
6. 等待进程清理
7. ray.init() + serve.start()
阶段二 —— 重新初始化:
8. Controller.__init__(config, runtime_env)
9. 通知主线程 → 重新运行训练循环就地重启
就地重启复用现有的 placement group,将服务恢复到当前步数:
1. 保存当前步数(通过 HTTP GET /get_step)
2. 停止心跳线程
3. 停止旧部署(HTTP POST /stop_service)
4. 删除 Ray Serve 部署
5. 验证/重建 placement group
6. 重新部署服务
7. 恢复步数(HTTP POST /set_step)
8. 重新运行服务任务配置参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
--use-health-check | 标志 | False | 启用全局健康检查系统 |
--max-global-restart | 整数 | 3 | 达到最大全局重启次数后强制终止 |
编程接口
python
from relax.utils.health_system import HealthManager
# 创建健康管理器(自定义检查间隔)
health_manager = HealthManager(check_interval=1.0)
# 启动(设置回调)
health_manager.start(on_unhealthy=handle_unhealthy_service)
# 查询健康状态
health = health_manager.get_service_health("actor")
print(health) # {"healthy": True, "error": None, "current_step": 42, ...}
# 停止
health_manager.stop(timeout=2.0)健康日志
启用健康检查后,您将看到如下日志:
[INFO] Global health check system enabled
[INFO] Health checker started
[INFO] HealthManager initialized
[WARNING] Service actor is unhealthy: RayTaskError(OutOfMemoryError), triggering restart
[INFO] Restarting service 'actor'...
[WARNING] Triggering global restart due to: actor failure
[INFO] === Starting GLOBAL restart #1 (max=3) ===
[INFO] [Global Restart] Health manager stopped
[INFO] [Global Restart] Deleted Ray Serve deployment 'actor'
[INFO] [Global Restart] Ray shutdown completed
[INFO] [Global Restart] Ray re-initialized
[INFO] [Global Restart] Controller re-initialized from zero via __init__
[INFO] === Global restart completed, main thread signaled ===
[INFO] Global restart completed, re-running training loop调试端点
服务暴露 HTTP 端点用于调试和恢复:
| 端点 | 方法 | 说明 |
|---|---|---|
/{role}/get_step | GET | 获取当前训练步数 |
/{role}/set_step?step=N | POST | 设置训练步数 |
/{role}/stop_service | POST | 优雅停止服务 |
/{role}/mark_unhealthy_for_testing | GET | 强制服务上报不健康状态(调试用) |
示例:
bash
# 检查 actor 步数
curl http://localhost:8000/actor/get_step
# 强制 actor 不健康(触发重启)
curl http://localhost:8000/actor/mark_unhealthy_for_testing最佳实践
- 生产环境务必启用:在生产训练中使用
--use-health-check - 设置合适的最大重启次数:
--max-global-restart 3是合理的默认值;长时间训练可适当增大 - 监控日志:关注重复出现的重启模式,这可能表明存在持续性问题
- 频繁保存检查点:使用
--save-interval确保重启不会丢失太多进度 - 使用异步保存:
--async-save防止检查点保存阻塞训练
故障排除
健康检查未触发恢复
- 确认启动命令中包含
--use-health-check - 检查服务是否在故障时正确调用了
report_error() - 对于心跳超时检测,服务崩溃后需等待至少 120 秒
全局重启失败
- 检查日志中的
[Global Restart] Failed to ...消息 - 如果
ray.shutdown()失败,残留进程可能占用 GPU 显存 - 如果超过最大重启次数,需排查反复失败的根本原因
服务重启后未恢复
- 检查 placement group 是否成功重建
- 验证服务步数是否正确恢复
- 检查新服务是否有 NCCL/分布式通信组问题
相关文档
- Metrics 服务 - 监控服务指标
- 通知系统 - 健康问题告警
- 架构设计 - 了解系统设计
