Skip to content

健康检查管理器

健康检查管理器为 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_stepGET获取当前训练步数
/{role}/set_step?step=NPOST设置训练步数
/{role}/stop_servicePOST优雅停止服务
/{role}/mark_unhealthy_for_testingGET强制服务上报不健康状态(调试用)

示例:

bash
# 检查 actor 步数
curl http://localhost:8000/actor/get_step

# 强制 actor 不健康(触发重启)
curl http://localhost:8000/actor/mark_unhealthy_for_testing

最佳实践

  1. 生产环境务必启用:在生产训练中使用 --use-health-check
  2. 设置合适的最大重启次数--max-global-restart 3 是合理的默认值;长时间训练可适当增大
  3. 监控日志:关注重复出现的重启模式,这可能表明存在持续性问题
  4. 频繁保存检查点:使用 --save-interval 确保重启不会丢失太多进度
  5. 使用异步保存--async-save 防止检查点保存阻塞训练

故障排除

健康检查未触发恢复

  1. 确认启动命令中包含 --use-health-check
  2. 检查服务是否在故障时正确调用了 report_error()
  3. 对于心跳超时检测,服务崩溃后需等待至少 120 秒

全局重启失败

  1. 检查日志中的 [Global Restart] Failed to ... 消息
  2. 如果 ray.shutdown() 失败,残留进程可能占用 GPU 显存
  3. 如果超过最大重启次数,需排查反复失败的根本原因

服务重启后未恢复

  1. 检查 placement group 是否成功重建
  2. 验证服务步数是否正确恢复
  3. 检查新服务是否有 NCCL/分布式通信组问题

相关文档

基于 Apache 2.0 许可发布