Skip to content

弹性 Rollout 扩缩容

概述

弹性 Rollout 扩缩容(Elastic Rollout Scaling) 允许用户在训练运行时动态调整 Rollout 推理引擎的数量,无需中断训练流程。在 RL 训练中,60~70% 的时间消耗在 Rollout(样本生成)阶段,弹性扩缩容可以根据实际需求灵活增减推理资源,显著提升资源利用效率和训练吞吐量。

适用场景

场景说明
训练瓶颈在推理Rollout 生成速度跟不上 Actor 训练速度,大量请求堆积,扩容 Rollout 引擎加速样本生成
集群资源释放训练进入后期(如 response length 已降低并收敛),缩容释放 GPU 给其他任务
跨集群联邦推理接入其他集群已部署的 SGLang 引擎,无需在同一 Ray 集群内分配资源
弹性资源池利用抢占式实例或空闲资源临时扩容,资源回收时自动缩容

前置条件

  • 训练必须使用 全异步模式(Fully Async),即启动参数中包含 --fully-async
  • Rollout 引擎使用 SGLang 作为推理后端
  • 训练后端使用 Megatron

TIP

弹性扩缩容仅在全异步模式下可用。在全异步模式中,Rollout 独占 GPU 资源并作为独立服务运行,天然适合弹性扩缩。关于全异步模式的更多信息,请参阅 全异步训练流水线


设计特色

服务化 API

弹性扩缩容通过 HTTP REST API 提供,与训练流程完全解耦。用户或外部调度系统可以通过标准 HTTP 请求触发扩缩容操作,无需修改训练代码或重启训练任务。

两种扩容模式

模式适用场景说明
ray_native同集群扩容指定目标引擎总数,Relax 自动在当前 Ray 集群内申请资源、启动新引擎
external跨集群/联邦扩容传入已部署的外部 SGLang 引擎地址,Relax 连接、同步权重并接入流量

核心设计亮点

  • 异步非阻塞:扩缩容操作异步执行,不阻塞训练主循环
  • 幂等性:相同参数的重复请求结果一致,安全重试无副作用
  • 互斥保护:同一时刻只允许一个扩/缩容操作执行,避免资源竞争
  • 取消支持:进行中的扩容请求可随时取消,自动回滚已分配的资源
  • 优雅缩容:缩容时先停止流量分配,等待在途请求处理完成,再释放资源
  • 初始引擎保护:由启动参数定义的初始引擎不可被缩容,只能缩容动态扩容的引擎

架构

                        ┌──────────────────────────────┐
                        │  External Scheduler / User   │
                        │   (curl / automation)        │
                        └──────────────┬───────────────┘
                                       │ HTTP REST API

┌─────────────────────────────────────────────────────────────────────┐
│              Rollout Service (relax/components/rollout.py)          │
│                    Ray Serve Ingress + FastAPI                      │
│                                                                     │
│    POST /scale_out        GET /engines       POST /scale_in         │
│    GET  /scale_out/{id}                      GET  /scale_in/{id}    │
│    POST /scale_out/{id}/cancel                                      │
└──────────────────────────────┬──────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────┐
│      RolloutManager (relax/distributed/ray/rollout.py)              │
│                  Ray Actor                                          │
│                                                                     │
│    scale_out()          scale_in()          get_engines_info()      │
│    ┌──────────┐         ┌──────────┐        ┌──────────────┐        │
│    │Create    │         │Select    │        │Query engine  │        │
│    │EngineGrp │         │targets   │        │status        │        │
│    │Health chk│         │Drain     │        └──────────────┘        │
│    │DCS reg   │         │Remove    │                                │
│    │Router reg│         │Cleanup   │                                │
│    └──────────┘         └──────────┘                                │
└──────────────────────────────┬──────────────────────────────────────┘

               ┌───────────────┼───────────────┐
               ▼               ▼               ▼
        ┌────────────┐  ┌────────────┐  ┌─────────────────┐
        │ SGLang     │  │ SGLang     │  │  DCS            │
        │ Router     │  │ Engine(s)  │  │  Coordinator    │
        │ (routing)  │  │ (inference)│  │  (initial eng)  │
        └────────────┘  └────────────┘  └─────────────────┘

关键组件职责:

组件职责
Rollout ServiceFastAPI 层,接收 HTTP 请求,转发给 RolloutManager
RolloutManager核心执行层,管理引擎生命周期、权重同步、状态机
SGLang Router请求路由层,负责将推理请求分发到各引擎(cache-aware 策略)
SGLang Engine推理引擎,执行 LLM 生成任务
DCS Coordinator权重分发服务,仅管理初始引擎的拓扑信息和权重广播

扩容(Scale-Out)

状态机

扩容请求经历以下状态流转:

PENDING → CREATING/CONNECTING → HEALTH_CHECKING → WEIGHT_SYNCING → READY → ACTIVE
    ↓            ↓                    ↓                ↓
  CANCELLED    FAILED              FAILED           FAILED
状态说明
PENDING请求已接收,等待处理
CREATING(ray_native) 正在创建 Ray Actor 和启动 SGLang 引擎
CONNECTING(external) 正在连接外部引擎
HEALTH_CHECKING引擎启动/连接完成,正在健康检查
WEIGHT_SYNCING健康检查通过,正在同步最新模型权重
READY权重同步完成,已注册到 Router
ACTIVE正在接收并处理推理请求
FAILED扩容失败(任意阶段出错)
CANCELLED用户主动取消

API 参考

发起扩容

bash
# ray_native 模式:扩容到 6 个引擎
curl -X POST http://<rollout-host>/rollout/scale_out \
  -H "Content-Type: application/json" \
  -d '{
    "num_replicas": 6,
    "timeout_secs": 300
  }'

# external 模式:接入外部引擎
curl -X POST http://<rollout-host>/rollout/scale_out \
  -H "Content-Type: application/json" \
  -d '{
    "engine_urls": [
      "http://192.168.1.100:30000",
      "http://198.51.100.101:30000"
    ]
  }'

请求参数:

参数类型默认值说明
model_namestring"default"目标模型名
num_replicasint0目标引擎总数(绝对值)。>0 时使用 ray_native 模式
engine_urlslist[str][]外部引擎地址列表。num_replicas=0 时使用 external 模式
timeout_secsfloatNone操作超时时间(秒),默认使用 --scale-out-timeout

响应示例:

json
{
  "request_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "PENDING",
  "message": "Scale-out request accepted"
}

查询扩容状态

bash
curl http://<rollout-host>/rollout/scale_out/550e8400-e29b-41d4-a716-446655440000

响应示例:

json
{
  "request_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "WEIGHT_SYNCING",
  "model_name": "default",
  "num_replicas": 6,
  "engine_urls": [],
  "engine_ids": ["engine_4", "engine_5"],
  "failed_engines": [],
  "created_at": 1709827200.0,
  "updated_at": 1709827215.0,
  "error_message": null,
  "weight_version": null
}

列出所有扩容请求

bash
# 列出所有请求
curl http://<rollout-host>/rollout/scale_out

# 按状态过滤
curl "http://<rollout-host>/rollout/scale_out?status=PENDING"

# 按模型名过滤
curl "http://<rollout-host>/rollout/scale_out?model_name=default&status=ACTIVE"

取消单个扩容请求

bash
curl -X POST http://<rollout-host>/rollout/scale_out/550e8400-e29b-41d4-a716-446655440000/cancel

批量取消扩容请求

bash
# 预览将要取消的请求(dry-run)
curl -X POST http://<rollout-host>/rollout/scale_out_cancel \
  -H "Content-Type: application/json" \
  -d '{"dry_run": true}'

# 取消所有 PENDING 状态的请求
curl -X POST http://<rollout-host>/rollout/scale_out_cancel \
  -H "Content-Type: application/json" \
  -d '{"status_filter": "PENDING"}'

幂等性保证

  • ray_native 模式num_replicas 是绝对目标值。如果当前引擎数(含正在创建中的)已达到或超过目标值,返回 NOOP,不执行任何操作
  • external 模式:系统自动过滤掉已在活跃列表或进行中请求中的引擎地址,仅接入新地址

权重同步机制

新引擎启动后必须同步最新模型权重才能接收推理请求。系统采用 remote instance weight sync 方式为 scaled-out 出来的引擎进行第一次权重同步:

权重同步流程

工作流程

  1. 引擎启动时跳过 DCS 注册:Scaled-out 引擎设置 skip_dcs_registration=True,不注册到 DCS Coordinator
  2. 引擎立即注册到 Router:健康检查通过后立即注册到 SGLang Router,可开始接收请求(使用旧权重)
  3. Actor 触发权重同步:在 Actor 的 update_weights_fully_async() 完成后,调用 RolloutManager.sync_weights_for_scaled_out_engines()
  4. 权重同步:从 seed engine(初始引擎)通过 NCCL Broadcast 直接传输权重到 scaled-out 引擎

前提条件

权重同步依赖健康的 seed engine,必须满足以下条件:

条件失败时行为
存在健康的 seed engine权重同步失败,引擎使用旧权重处理请求
seed engine 有有效 weight_version权重同步失败,引擎使用旧权重处理请求
能获取 seed engine 的 URL权重同步失败,引擎使用旧权重处理请求

特点

  • 代码简单:避免 DCS 拓扑管理的复杂性
  • 不影响 DCS 稳定性:Scaled-out 引擎不参与 DCS 拓扑,动态扩缩容不影响现有引擎的权重同步
  • 自动触发:权重同步在 Actor 的 DCS 同步完成后自动触发,无需额外配置
  • 失败快速返回:权重同步失败时直接返回,引擎保持运行状态,可正常处理请求(使用旧权重)

并发保护

Direct Sync 期间会设置 _is_weight_updating = True,阻止并发的权重更新操作。

WARNING

权重同步失败时,scaled-out 引擎将使用旧权重处理请求。如果对权重一致性要求严格,可以在 Router 中先标记为不健康,权重同步完成后再标记为健康。


缩容(Scale-In)

状态机

缩容请求经历以下状态流转:

PENDING → DRAINING → REMOVING → COMPLETED
    ↓         ↓          ↓
  FAILED    FAILED     FAILED
状态说明
PENDING请求已接收,正在选择待移除引擎
DRAINING已停止新请求调度,等待在途请求处理完成
REMOVING正在注销 DCS、关闭进程、释放资源
COMPLETED缩容完成,资源已释放
FAILED缩容失败

API 参考

发起缩容

bash
# 按目标数量缩容:保留 4 个引擎
curl -X POST http://<rollout-host>/rollout/scale_in \
  -H "Content-Type: application/json" \
  -d '{
    "num_replicas": 4
  }'

# 按地址缩容:移除指定引擎
curl -X POST http://<rollout-host>/rollout/scale_in \
  -H "Content-Type: application/json" \
  -d '{
    "engine_urls": [
      "http://192.168.1.100:30000"
    ]
  }'

# 强制缩容:跳过 drain 等待
curl -X POST http://<rollout-host>/rollout/scale_in \
  -H "Content-Type: application/json" \
  -d '{
    "num_replicas": 4,
    "force": true
  }'

# 预览缩容(dry-run)
curl -X POST http://<rollout-host>/rollout/scale_in \
  -H "Content-Type: application/json" \
  -d '{
    "num_replicas": 4,
    "dry_run": true
  }'

请求参数:

参数类型默认值说明
model_namestring"default"目标模型名
num_replicasint0目标剩余引擎数(绝对值)。>0 时优先使用此模式
engine_urlslist[str][]指定移除的引擎地址列表
forceboolfalse强制缩容,跳过 drain 等待
timeout_secsfloatNone操作超时时间(秒)
dry_runboolfalse仅预览,不实际执行缩容

响应示例:

json
{
  "request_id": "660e8400-e29b-41d4-a716-446655441111",
  "status": "PENDING",
  "message": "Scale-in request accepted"
}

查询缩容状态

bash
curl http://<rollout-host>/rollout/scale_in/660e8400-e29b-41d4-a716-446655441111

缩容策略

缩容遵循以下原则:

  1. LIFO(后进先出):优先移除最近一次扩容添加的引擎
  2. 初始引擎保护:由 --rollout-num-gpus--rollout-num-gpus-per-engine 启动参数定义的初始引擎不可被缩容。如果 num_replicas 小于初始引擎数,请求返回 HTTP 400
  3. 优雅退出:缩容前先在 Router 中隔离流量(标记为不健康),等待在途请求完成后再释放资源
  4. 部分成功语义:已成功移除的引擎不会回滚,仅报告失败部分

WARNING

缩容操作会先检查权重同步状态。如果当前正在进行权重更新(update_weights_fully_async),缩容会等待同步完成后再执行,以避免 NCCL 通信组状态不一致。


查询引擎状态

bash
curl http://<rollout-host>/rollout/engines

响应示例:

json
{
  "models": {
    "default": {
      "engines": [
        {
          "engine_id": "engine_0",
          "url": "http://198.51.100.10:30000",
          "status": "ACTIVE",
          "is_healthy": true
        },
        {
          "engine_id": "engine_1",
          "url": "http://198.51.100.11:30000",
          "status": "ACTIVE",
          "is_healthy": true
        }
      ]
    }
  },
  "total_engines": 2
}

配置参数

扩容参数

参数类型默认值说明
--scale-out-timeoutfloat1800扩容操作总超时(秒),包括引擎启动、健康检查、权重同步等
--scale-out-partial-success-policystringrollback_all部分成功处理策略。rollback_all:任一引擎失败则全部回滚;keep_partial:保留成功的引擎

缩容参数

参数类型默认值说明
--scale-in-drain-timeoutfloat30流量排空超时(秒),超时后强制中止在途请求
--scale-in-shutdown-timeoutfloat20引擎优雅关闭超时(秒),超时后使用 ray.kill 强制终止

配置示例

bash
ray job submit -- python3 relax/entrypoints/train.py \
    --fully-async \
    --rollout-num-gpus 4 \
    --rollout-num-gpus-per-engine 1 \
    --scale-out-timeout 600 \
    --scale-out-partial-success-policy keep_partial \
    --scale-in-drain-timeout 60 \
    --scale-in-shutdown-timeout 30 \
    ... # 其他训练参数

使用示例

场景一:训练推理瓶颈,扩容 Rollout

bash
# 1. 查看当前引擎状态
curl http://localhost:8000/rollout/engines
# 返回:total_engines = 4

# 2. 扩容到 8 个引擎
curl -X POST http://localhost:8000/rollout/scale_out \
  -H "Content-Type: application/json" \
  -d '{"num_replicas": 8}'
# 返回:request_id = "abc-123", status = "PENDING"

# 3. 轮询扩容状态
curl http://localhost:8000/rollout/scale_out/abc-123
# 状态流转:PENDING → CREATING → HEALTH_CHECKING → WEIGHT_SYNCING → READY

# 4. 确认扩容完成
curl http://localhost:8000/rollout/engines
# 返回:total_engines = 8

场景二:接入跨集群引擎

bash
# 在另一个集群上启动 SGLang 引擎(确保模型路径和配置一致)
# python -m sglang.launch_server --model-path /path/to/model --port 30000

# 接入外部引擎
curl -X POST http://localhost:8000/rollout/scale_out \
  -H "Content-Type: application/json" \
  -d '{
    "engine_urls": [
      "http://192.0.2.50:30000",
      "http://192.0.2.51:30000"
    ]
  }'

场景三:训练后期缩容释放资源

bash
# 1. 先预览会移除哪些引擎
curl -X POST http://localhost:8000/rollout/scale_in \
  -H "Content-Type: application/json" \
  -d '{"num_replicas": 4, "dry_run": true}'

# 2. 确认后执行缩容
curl -X POST http://localhost:8000/rollout/scale_in \
  -H "Content-Type: application/json" \
  -d '{"num_replicas": 4}'

# 3. 查询缩容状态
curl http://localhost:8000/rollout/scale_in/<request_id>

错误处理

常见错误码

HTTP 状态码含义处理建议
200操作成功-
400请求参数无效(如缩容目标小于初始引擎数)检查请求参数
404请求 ID 不存在检查请求 ID 是否正确
409存在进行中的扩缩容操作等待当前操作完成,或取消后重试
500内部错误查看训练日志排查

扩容失败处理

  • 默认使用 rollback_all 策略:任一引擎扩容失败时,已创建的引擎全部回滚释放
  • 可通过 --scale-out-partial-success-policy keep_partial 切换为保留成功的引擎

缩容失败处理

  • 缩容采用 部分成功 语义:已成功移除的引擎不会回滚
  • 部分失败时返回 COMPLETED 状态并附带错误信息,用户可针对失败部分重试

互斥与安全

约束说明
扩缩容互斥同一时刻只允许一个扩容或缩容操作执行,并发请求返回 HTTP 409
权重同步互斥缩容在 Drain 前检查权重同步状态,如正在进行权重更新则等待完成
健康监控集成缩容的引擎会被标记为 "intentionally removed",不会被健康检查系统自动恢复
权重同步Scaled-out 引擎通过 Remote Instance Sync 同步权重,不参与 DCS 拓扑管理

Autoscaler 自动扩缩

注意

当前 Autoscaler 仅调用 ray_native 接口进行扩缩操作,必须结合 Ray 的 Autoscaling 以及集群弹性能力配合使用。如果要基于 K8s 搭建扩缩,建议参考 K8s HPA + KEDA 弹性扩缩容集成方案

Autoscaler 服务提供完全自动化的 Rollout 引擎扩缩容,基于实时指标采集自动触发扩缩操作。通过可配置的策略,系统自动监控引擎性能并在需要时触发扩容或缩容,无需人工干预。

架构

┌─────────────────────────────────────────────────────────────┐
│                    AutoscalerService                        │
│                    (Ray Serve Deployment)                   │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐     │
│  │   Metrics    │→  │   Scaling    │→  │   State      │     │
│  │   Collector  │   │   Decision   │   │   Manager    │     │
│  └──────────────┘   └──────────────┘   └──────────────┘     │
│         │                  │                  │             │
│         ▼                  ▼                  ▼             │
│  ┌──────────────────────────────────────────────────────┐   │
│  │                    State Store                       │   │
│  │  - engine_metrics_history (sliding window)           │   │
│  │  - last_scale_event_time                             │   │
│  │  - pending_scale_requests                            │   │
│  └──────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
         │                                         │
         │ HTTP GET /metrics                       │ HTTP POST /scale_out
         │ (per engine)                            │ /scale_in
         ▼                                         ▼
┌─────────────────┐                     ┌─────────────────────┐
│  SGLang Engine  │  ...                │   Rollout Service   │
│  (TP=2)         │                     │   (scaling API)     │
└─────────────────┘                     └─────────────────────┘

指标选择

Autoscaler 采用分层指标体系进行扩缩决策:

主扩缩指标

指标名类型描述扩容触发条件缩容触发条件
sglang:token_usagegaugeKV Cache 利用率 (0.0 - 1.0)> 0.85< 0.3
sglang:num_queue_reqsgauge等待队列中的请求数> N × 引擎数= 0 (持续)
sglang:queue_time_secondshistogram排队等待时间 (P95)> 5.0s-

辅助验证指标

指标名类型用途
sglang:gen_throughputgauge生成吞吐量 (tok/s)
sglang:time_to_first_token_secondshistogramTTFT P95/P99 (服务质量)
sglang:inter_token_latency_secondshistogram解码延迟 (资源健康度)
sglang:num_running_reqsgauge并发请求数

资源约束指标

指标名类型用途
sglang:max_total_num_tokensgauge单引擎最大容量
sglang:num_used_tokensgauge当前占用 tokens

扩缩策略

扩容策略

满足以下任意条件即触发扩容:

条件阈值持续时长
token_usage_high> 0.8530s
queue_backlog> 10/引擎20s
queue_latency_highP95 > 5.0s15s
ttft_highP95 > 10.0s15s

扩容幅度计算:

python
# 基于利用率压力
if token_usage > 0.9:
    usage_delta = int((token_usage - 0.7) / 0.1)  # 每 10% 超额 +1 引擎
else:
    usage_delta = 0

# 基于队列积压
queue_delta = max(0, (queue_depth - engines * 5) // 20)

# 取较大值,限制最大扩容幅度
delta = min(max(usage_delta, queue_delta, 1), 4)

缩容策略

满足以下全部条件才触发缩容:

条件阈值持续时长
token_usage_low< 0.3120s
no_queue= 0120s
throughput_stable方差 < 0.160s

保守策略:

  • 单次缩容最多移除 1 个引擎
  • 预测缩容后利用率仍 < 50% 才允许执行
  • 初始引擎(启动参数定义)受保护,不会被缩容

冷却期与防抖动

设置默认值描述
scale_out_cooldown_secs60s扩容后等待时间
scale_in_cooldown_secs300s缩容后等待时间
condition_window_secs60s条件历史时间窗口

配置参数

启用 Autoscaler

Autoscaler 通过 --autoscaler-config 参数指定 YAML 配置文件来启用。如果不提供此参数,autoscaler 默认禁用。

bash
ray job submit -- python3 relax/entrypoints/train.py \
    --fully-async \
    --autoscaler-config relax/utils/autoscaler/autoscaler.yaml \
    ... # 其他训练参数

配置文件格式

创建一个 YAML 配置文件,格式如下:

yaml
# relax/utils/autoscaler/autoscaler.yaml

# 是否启用 autoscaler(使用此配置文件时设置为 true)
enabled: true

# 引擎数量边界
min_engines: 1
max_engines: 32

# 冷却期(秒)
scale_out_cooldown_secs: 60.0
scale_in_cooldown_secs: 300.0

# 时间间隔(秒)
metrics_interval_secs: 10.0
evaluation_interval_secs: 30.0
condition_window_secs: 60.0

# 服务端点(会被命令行参数 rollout_service_url 覆盖)
rollout_service_url: "http://localhost:8000/rollout"

# 扩容策略:满足任意条件即触发
scale_out_policy:
  token_usage_threshold: 0.85
  queue_depth_per_engine: 10
  queue_time_p95_threshold: 5.0
  ttft_p95_threshold: 10.0
  condition_duration_secs: 30.0
  max_delta: 4

# 缩容策略:满足全部条件才触发
scale_in_policy:
  token_usage_threshold: 0.3
  queue_depth_threshold: 0
  throughput_variance_threshold: 0.1
  condition_duration_secs: 120.0
  max_delta: 1
  projected_usage_max: 0.5

配置字段说明

字段类型默认值描述
enabledbooltrue是否启用 autoscaler
min_enginesint1最小引擎数
max_enginesint32最大引擎数
scale_out_cooldown_secsfloat60.0扩容冷却期(秒)
scale_in_cooldown_secsfloat300.0缩容冷却期(秒)
metrics_interval_secsfloat10.0指标采集间隔(秒)
evaluation_interval_secsfloat30.0扩缩评估间隔(秒)
condition_window_secsfloat60.0条件历史时间窗口

扩容策略字段:

字段类型默认值描述
token_usage_thresholdfloat0.85扩容 token 使用率阈值
queue_depth_per_engineint10每引擎队列深度阈值
queue_time_p95_thresholdfloat5.0P95 排队时间阈值(秒)
ttft_p95_thresholdfloat10.0P95 TTFT 阈值(秒)
condition_duration_secsfloat30.0条件持续时长
max_deltaint4单次最大扩容引擎数

缩容策略字段:

字段类型默认值描述
token_usage_thresholdfloat0.3缩容 token 使用率阈值
queue_depth_thresholdint0队列深度阈值
throughput_variance_thresholdfloat0.1最大吞吐量方差
condition_duration_secsfloat120.0条件持续时长
max_deltaint1单次最大缩容引擎数
projected_usage_maxfloat0.5缩容后预测利用率上限

API 参考

获取 Autoscaler 状态

bash
curl http://localhost:8000/autoscaler/status

响应示例:

json
{
  "enabled": true,
  "running": true,
  "current_engines": 4,
  "min_engines": 2,
  "max_engines": 16,
  "last_scale_time": 1709827200.0,
  "last_scale_action": "scale_out",
  "last_decision": {
    "action": "scale_out",
    "delta": 2,
    "reason": "Conditions met: token_usage_high, queue_backlog"
  },
  "pending_requests": [],
  "recent_metrics": {
    "num_engines": 4,
    "avg_token_usage": 0.92,
    "total_queue_reqs": 45
  }
}

启用/禁用 Autoscaler

bash
# 启用
curl -X POST http://localhost:8000/autoscaler/enable \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}'

# 禁用
curl -X POST http://localhost:8000/autoscaler/enable \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}'

获取条件状态

bash
curl http://localhost:8000/autoscaler/conditions

响应示例:

json
{
  "conditions": {
    "token_usage_high": {"type": "scale_out", "triggered": true},
    "queue_backlog": {"type": "scale_out", "triggered": false},
    "token_usage_low": {"type": "scale_in", "triggered": false},
    "no_queue": {"type": "scale_in", "triggered": true}
  },
  "metrics": {
    "avg_token_usage": 0.88,
    "total_queue_reqs": 2
  }
}

健康检查

bash
curl http://localhost:8000/autoscaler/health

查询扩缩历史

查询 autoscaler 触发的所有扩缩操作历史:

bash
# 获取所有历史记录(最新在前)
curl http://localhost:8000/autoscaler/scale_history

# 限制返回条数
curl "http://localhost:8000/autoscaler/scale_history?limit=10"

# 按操作类型过滤
curl "http://localhost:8000/autoscaler/scale_history?action=scale_out"
curl "http://localhost:8000/autoscaler/scale_history?action=scale_in"

响应示例:

json
{
  "history": [
    {
      "request_id": "550e8400-e29b-41d4-a716-446655440000",
      "action": "scale_out",
      "status": "ACTIVE",
      "triggered_at": 1709827200.0,
      "completed_at": 1709827230.0,
      "from_engines": 4,
      "to_engines": 6,
      "delta": 2,
      "reason": "Conditions met: token_usage_high, queue_backlog",
      "triggered_conditions": ["token_usage_high", "queue_backlog"],
      "metrics_snapshot": {
        "avg_token_usage": 0.92,
        "total_queue_reqs": 45
      },
      "error_message": null
    }
  ],
  "total_count": 5,
  "action_filter": null,
  "limit": 100
}

历史记录字段说明:

字段类型描述
request_idstringRollout 服务返回的唯一请求 ID
actionstringscale_outscale_in
statusstring最终状态:ACTIVECOMPLETEDFAILEDCANCELLED
triggered_atfloat请求触发时间戳
completed_atfloat请求完成时间戳
from_enginesint扩缩前引擎数
to_enginesint扩缩后引擎数
deltaint新增/移除的引擎数
reasonstring扩缩原因描述
triggered_conditionslist触发此次扩缩的条件列表
metrics_snapshotdict决策时刻的指标快照
error_messagestring失败时的错误信息

使用示例

bash
# 1. 创建自定义 autoscaler 配置文件
cat > my_autoscaler.yaml << 'EOF'
enabled: true
min_engines: 2
max_engines: 8
scale_out_policy:
  token_usage_threshold: 0.80
  max_delta: 2
scale_in_policy:
  token_usage_threshold: 0.25
EOF

# 2. 启动训练并启用 autoscaler
ray job submit -- python3 relax/entrypoints/train.py \
    --fully-async \
    --autoscaler-config my_autoscaler.yaml

# 3. 监控 autoscaler 状态
watch -n 5 'curl -s http://localhost:8000/autoscaler/status | jq'

# 4. 查看条件触发情况
curl http://localhost:8000/autoscaler/conditions

# 5. 临时禁用 autoscaler
curl -X POST http://localhost:8000/autoscaler/enable \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}'

监控面板

使用内置 TUI 监控器实时查看 autoscaler 指标:

bash
python -m relax.utils.autoscaler.monitor --url http://localhost:8000/autoscaler

Autoscaler Monitor

键盘控制:q 退出,r 强制刷新。

关键设计原则

原则描述
多条件逻辑扩容:任一条件触发;缩容:所有条件必须同时满足
持续时长窗口条件必须持续指定时长才触发,避免瞬时波动
冷却期保护防止短时间内连续扩缩容操作
保守缩容单次最多缩 1 个引擎,且预测缩容后利用率 < 50%
pending 检查有未完成的扩缩请求时不触发新操作
硬边界保护min_enginesmax_engines 严格限制

延伸阅读

基于 Apache 2.0 许可发布