预计阅读 6 分钟

生产 4:SLO 与容量规划

谁该读这一篇? 要给业务定 SLO、做容量规划、做错误预算管理的 SRE / TL。 前置阅读: 03-monitoring.md05-distributed/02-data-parallelism.md耗时: 30 分钟 学完能: 1. 写一份可执行的 SLO 文档; 2. 用容量公式算出"目标 QPS 需要多少副本"; 3. 用压测数据反推容量; 4. 给错误预算定执行规则; 5. 区分 chat / agent / embedding 各自典型 SLO。


1. SLO 三要素

每个 SLO 包含:

  • SLI:服务等级指标(measurable)。
  • 目标:百分位 / 阈值(如 p99 < 500ms)。
  • 窗口:评估时间(如 30 天滚动)。

例:

SLO-1: Chat TTFT p99 < 500 ms, evaluated over 30-day rolling window, target 99%
SLO-2: Chat TPOT p99 < 50 ms, evaluated over 30-day rolling window, target 99.5%
SLO-3: Chat success rate > 99.9% over 30-day rolling window

2. 不同业务的典型 SLO

业务 TTFT TPOT Success 备注
Chat(实时对话) < 500 ms p99 < 50 ms p99 > 99.9% 用户感知最敏感
Code assist < 800 ms p99 < 60 ms p99 > 99.9% tab 自动补全
总结 / RAG < 2 s p99 < 80 ms p99 > 99.5% 长 prompt
Agent < 1 s p99 / step < 60 ms p99 > 99% 多步累计
Batch embedding N/A N/A throughput > 99% 无时延 SLO
Function call < 500 ms p99 < 50 ms p99 > 99.5% + 结构 100% 加结构成功率 SLO

3. 容量公式(再回顾)

$$N = \left\lceil \frac{Q \cdot T_e}{C} \right\rceil$$
  • $Q$:目标 QPS
  • $T_e$:平均请求处理时间(秒)
  • $C$:单副本最大并发

例:

  • $Q$ = 50 QPS, $T_e$ = 2s, $C$ = 64 → $N$ = ⌈100/64⌉ = 2 副本。

但要留余量:

N_provision = N × (1 + safety_margin) / (1 - peak_to_avg)
  • safety_margin:30% 常规
  • peak_to_avg:业务峰值除以平均,0.3-0.5

实际:N_provision = 2 × 1.3 / (1 - 0.4) = 4.3 → 5 副本。


4. 用压测数据反推容量

跑 sweep(07-hands-on/02-benchmark-throughput.md §6):

request_rate vs TTFT p99:
  rate=8: p99=120 ms
  rate=16: p99=180 ms
  rate=32: p99=350 ms
  rate=64: p99=890 ms       ← 突破 SLO
  rate=128: p99=2400 ms

拐点 ≈ 64 QPS 时 SLO 破线。所以单副本"SLO 安全容量" = 50 QPS(留 20% 余量)。

实际部署:

  • 目标总 QPS:200
  • 单副本:50
  • 副本数:4 + 余量 = 6

5. 错误预算(Error Budget)

错误预算 = (1 - SLO_target) × 时间窗口

例: SLO 99.9% / 30 天:
  错误预算 = 0.001 × 30 × 24 × 60 = 43.2 分钟/月

错误预算用尽时的规则(可以抄):

用尽 做法
< 50% 正常发布
50% - 100% 暂停新功能,只做稳定性修复
> 100% Freeze 所有变更,专攻恢复

6. 长尾问题

LLM 请求长度差异巨大:

prompt: 100 - 8000 token
output: 10 - 2000 token

时延分布天然长尾。p99 = 4× mean 是常态。 设 SLO 时直接看 p99,不看 mean。


7. 多业务共用副本怎么算 SLO

副本同时跑 chat + agent + 总结
  chat 占 60%, SLO TTFT < 500ms
  agent 占 30%, SLO TTFT < 1000ms
  总结 占 10%, SLO TTFT < 2000ms

策略 A:按业务路由分流——chat 用 cache-aware policy 副本,总结用 FCFS。 策略 B:优先级调度——SGLang --enable-priority-scheduling,chat 高优先级。

如果业务 SLO 差异大,优先策略 A


8. 容量预测

业务 QPS 通常有:

  • 日内规律(早晚高峰)
  • 周内规律(工作日 vs 周末)
  • 长期增长(季度增长率)

监控记录 + 简单时序模型预测下个月峰值,提前扩容。 KEDA / HPA 可以做实时响应,但冷启动慢02-kubernetes.md §6),还是要提前规划。


9. 压测当作 SLO 验证

每周 / 每月做一次"SLO 验证测试":

# 模拟峰值流量持续 30 分钟
python -m sglang.bench_serving \
    --request-rate 100 \
    --num-prompts 180000 \
    --dataset-path realistic.json

跑完看 p99 是否仍在 SLO 内。 不在的话,问题:

  • 量化 / 模型版本变化?
  • 业务流量特征变化(prompt 变长)?
  • 副本数没跟上?

10. SLO 文档模板(抄走)

# Chat API SLO (V1)

## 业务背景
- 服务: chat-completion
- 用户: 内部 SaaS 客户
- 流量: 平均 50 QPS, 峰值 200 QPS

## SLI 定义
- TTFT: `histogram_quantile(0.99, rate(sglang_e2e_first_token_latency_seconds_bucket[5m]))`
- TPOT: `histogram_quantile(0.99, rate(sglang_inter_token_latency_seconds_bucket[5m]))`
- Success: `1 - rate(sglang_num_aborted[5m]) / rate(sglang_num_requests[5m])`

## SLO 目标 (30 天滚动)
- TTFT p99 < 500 ms, target 99%
- TPOT p99 < 50 ms, target 99.5%
- Success > 99.9%

## 错误预算
- TTFT: 7.2 hr/month
- TPOT: 3.6 hr/month
- Success: 43 min/month

## 错误预算执行规则
- < 50%: normal release
- 50-100%: freeze new features
- > 100%: full incident, all hands

## 容量规划
- 单副本: 50 QPS @ SLO
- 当前副本: 6
- 余量: 33% (handles 8 副本 = 400 QPS)

## SLO 评估
- 自动: weekly report from Prometheus
- 人工: monthly review by SRE + product

## 升级
- TTFT 改至 400 ms:需要产品同意 + 验证副本足够

11. 小结

  • SLO = SLI + 目标 + 窗口;分业务定。
  • 容量公式 $N = Q T_e / C$,加 30% 安全裕度。
  • 错误预算驱动发布节奏。
  • LLM 长尾天然存在,盯 p99 不盯 mean。
  • 周期压测 + 容量预测 + KEDA 自动扩缩。

12. 自检

  1. SLO 99.9% 在 30 天里允许多少分钟不达标?
答案 30 × 24 × 60 = 43200 分钟。 错误预算 = 0.1% × 43200 = **43.2 分钟/月**。 含义:连续 43 分钟服务不达标,或全月分散 43 分钟不达标,都会用尽预算。 实际:服务挂 5 分钟是 12% 预算消耗;一次 4 小时大故障直接超 5×。 SLO 99.99% 的话只剩 4.3 分钟/月——非常严格,通常只用于关键 API。
  1. 我业务峰值是平均 4×,副本怎么定?
答案 按峰值定,留一些余量: `N_provision = (Q_peak × T_e / C) × (1 + safety_margin)` 设平均 50 QPS,峰值 200,T_e=2s,C=64: - 平均需求:50×2/64 = 1.6 → 2 副本 - 峰值需求:200×2/64 = 6.25 → 7 副本 - 加 30% safety:7 × 1.3 = 9.1 → **10 副本** 配合 HPA:minReplicas=10 是固定底,maxReplicas=15 给突发。 不按峰值定的风险:峰值时排队 → TTFT 飙 → SLO 破。 省钱的高级技巧:用 spot / preemptible 跑"平峰副本"(4 个),HPA 拉起的"峰值副本"用按量。
  1. p99 / mean 比例 5×,意味着什么?
答案 严重长尾。意味着: (1) **mean 数字是骗人的**——大部分请求确实快,但 1% 用户体验极差。 (2) **SLO 设错了**:用 mean 定 SLO 时 99% 用户满意,1% 严重不满;SLO 必须看 p99/p999。 (3) **资源浪费**:为了让 p99 达标,要按"最长尾"配资源;mean 看似低利用率,实际是被长尾拖累。 (4) **业务根因**:长 prompt 占比、cache miss 异常、抢占级联、客户端重试、网络抖动等。 优化:找出 1% 慢请求的共性(长 prompt?特定 user?特定 tool?),针对性解决,比扩容划算。
  1. 错误预算用尽时该怎么办?
答案 严格按 SRE 流程: (1) **立刻 freeze 新功能上线**——所有变更必须是修复,不许新增风险。 (2) **召集 incident review**:拉齐 SRE + 产品 + 业务方,分析预算消耗在哪。 (3) **短期修复 + 长期改进**:本月稳定性专项,把根因(如 cache evict 策略 / 路由策略)改了。 (4) **下月评估**:(a) 如果 SLO 一直达不到,承认能力上限改 SLO;(b) 如果是流量增长,加投资扩容;(c) 如果是事故密集,做系统级整改。 关键:**用尽预算是信号,不是惩罚**。如果团队怕被惩罚,会偷偷不报错;要让大家敢于报、敢于讨论。
  1. Chat 和总结业务 SLO 差异大,部署上怎么处理?
答案 **物理隔离 + 各自 SLO**: - 部署独立的 SGLang 副本组(chat 用 chat-pool,总结用 sum-pool)。 - Router 按 model 字段 / tenant_id / API path 路由。 - 各 pool 独立 HPA、独立监控、独立 SLO。 - 优势:互不干扰,故障域隔离。 - 劣势:资源利用率低(chat 峰值时 sum 闲置)。 折中:**优先级调度共用**——同一副本启用 `--enable-priority-scheduling`,chat 请求 priority=高、总结 priority=低;总结业务在 chat 压力大时自动让步。 - 优势:资源摊薄。 - 劣势:总结 SLO 受 chat 影响。 实战:**对 SLO 严格的业务(chat)物理隔离**;批处理类业务(总结、embedding)走优先级共用。

13. 下一步

参考:Google SRE Book Ch. SLO / Error Budget。