跳到主要内容
推理优化

7.4 Goodput 与 SLO 感知调度:以有效吞吐为优化目标

Raw QPS 与 Goodput 的区别、SLO 的构成(TTFT/TPOT/端到端)、分位点约束的意义、SLO 感知调度的机制、Goodput 的测量方法

GoodputSLO分位点QoS调度TTFTTPOT

7.1 说过”SLO 盯分位点不盯均值”,7.2 说 DistServe 把优化目标改成 Goodput——这一节把这两个概念系统讲透。Raw QPS(每秒请求数)不等于用户体验:一个 90% 请求都超时的服务,QPS 再高也是废的。Goodput 就是”满足 SLO 的吞吐”,它把服务质量从”旁挂指标”变成”优化目标本身”。这一节也讲 SLO 感知调度怎么在运行时实现它。

📑 目录


1. 从 QPS 到 Goodput:指标革命

1.1 传统指标的问题

指标定义盲区
QPS / RPS每秒处理的请求数慢请求也算”处理”——超时请求同样计入
吞吐(Tokens/s)每秒生成 token 数不区分有效/无效输出
平均延迟请求延迟的算术平均尾部被均值掩盖(7.1 的干扰正是打尾部)

1.2 Goodput 的定义

Goodput=在 SLO 约束内完成的请求数/时间\text{Goodput} = \text{在 SLO 约束内完成的请求数} / \text{时间}

或等价地:Goodput=吞吐×SLO 达标率\text{Goodput} = \text{吞吐} \times \text{SLO 达标率}

📌 关键点:Goodput 是”达标的吞吐”——一个请求要么在 SLO 内完成(计入),要么超时(不计入)。它不是新指标,而是把服务质量乘进吞吐里。DistServe 把 goodput 作为系统优化目标,意味着调度器的每个决策都在为”SLO 内完成率”服务,而不是为”token 总数”服务。

1.3 为什么必须换指标

一个反直觉的事实:高吞吐与高 Goodput 在资源受限时互相矛盾。把并发拉满,吞吐确实涨,但每个请求都变慢、SLO 达标率暴跌——Raw QPS 上升而 Goodput 下降。服务型系统优化的是后者:

同一台机器、两种配置:
配置 A:并发 512 → 吞吐 5000 tok/s,SLO 达标率 99%  → Goodput ≈ 4950
配置 B:并发 2048 → 吞吐 9000 tok/s,SLO 达标率 50%  → Goodput ≈ 4500

配置 B 的”吞吐更高”,但用户感受到的是”一半请求太慢”。用 Goodput 选型,配置 A 才是赢家。


2. SLO 的解剖:用什么指标、卡什么阈值

2.1 LLM 服务的 SLO 指标集

SLO 指标覆盖阶段典型阈值(生产常见)
TTFT(首 token 时间)Prefill + 排队P95 < 1-3s(聊天场景)
TPOT / ITL(每 token 时间)DecodeP95 < 50-100ms
端到端延迟全程P95 < 10-30s(长输出按预期时长缩放)
错误率全程< 0.1-1%

2.2 SLO 的三个要素

一个完整的 SLO 语句包含三要素:

[指标] 的 [分位点] 要 [阈值] 以内
   │        │         │
  TTFT     P95       < 2s
  • 指标:TTFT / TPOT / 端到端 / 错误率
  • 分位点:P50 / P90 / P95 / P99(决定”允许多少请求慢”)
  • 阈值:具体毫秒/秒数(与业务场景强相关)

💡 提示:别把”延迟平均值 < 2s”当 SLO——那是伪 SLO。没有分位点的 SLO 无法约束尾部,而 7.1 已经证明 LLM 服务的尾部恰恰最脆弱。写 SLO 时强制自己写全三要素。

2.3 多阶段 SLO 的叠加

生产服务通常同时有 TTFT 和 TPOT 两个 SLO(甚至端到端)。两个都要满足

请求达标    TTFTT1 且 TPOT 各步T2\text{请求达标} \iff \text{TTFT} \le T_1 \ \text{且} \ \text{TPOT 各步} \le T_2

这也正是解耦的动机之一(7.1 的资源耦合):混合架构下同时守两个 SLO 很难,解耦后各守各的(7.6)。


3. 为什么分位点(P95/P99)而不是均值

3.1 均值掩盖尾部

一个典型的延迟分布(LLM 混合负载):95% 的请求 100ms 完成,5% 的请求 5s。均值 345ms 看着还行,但 P99 = 5s 已经不可用。均值是分布的单点摘要,对长尾无能为力。

3.2 尾部的业务含义

  • 用户对”慢”的感知是非线性的——最后一个慢请求毁掉整个交互体验
  • 下游系统(调用方)超时按分位点设计——你的 P99 超时,下游的重试风暴就来了
  • 分布式系统里尾部延迟会级联放大(tail at scale 现象)——单个服务的 P99 问题会传导到整条调用链

3.3 分位点的统计含义

  • P95:95% 的请求达标,5% 允许超时(约每 20 个请求允许 1 个慢)
  • P99:99% 达标(约每 100 个请求允许 1 个慢)

分位点越高,调度的”安全余量”要求越大——P99 SLO 比 P95 贵(需要更多资源余量),写 SLO 时按业务真实需求选,别盲目上 P99。

📌 关键点:分位点与资源的关系:达标分位点每上一个台阶,所需资源余量非线性增长(P99 的资源成本通常明显高于 P95)。生产实践:对外 SLO 写 P95,内部优化看 P99——既保体验又控成本。


4. Goodput 的测量:同一条曲线两种读数

Goodput 可以用负载-延迟曲线理解:

延迟(P95 TTFT)
  │              ┌────────── 超 SLO 区(不达标)
  │         ╱────┘
  │    ╱───┘        ← SLO 线(如 2s)
  │ ╱──┘
  │╱─┘  ← 达标区
  └───────────────────────→ 请求速率
      ↑                    ↑
    Raw 吞吐上限       Goodput 上限
  (延迟爆炸点)     (与 SLO 线的交点)
  • Raw 吞吐上限:系统”崩溃前”能扛的最大速率(延迟无约束)
  • Goodput 上限:延迟恰好压在 SLO 线下的最大速率
  • 两者之间的区域:看似能扛、实则不达标的”虚胖区”

💡 提示:压测时别只看”打爆了没”——在 SLO 线下找最大速率才是 Goodput 压测。流程:固定负载 → 逐步加压 → 记录 P95 延迟与 SLO 线的交点 → 该点的 QPS 就是 Goodput 上限。7.6 实战会完整走一遍。


5. SLO 感知调度:运行时怎么保 Goodput

指标定了,调度器怎么执行?SLO 感知调度(SLO-aware scheduling)的常用机制:

5.1 准入控制(Admission Control)

拒绝/降级会拖垮 SLO 的请求——队列已深时新请求要么排队等(TTFT 爆)要么直接拒绝(错误率涨)。调度器维护”当前资源状态 + SLO 余量”的估计,超限时:

  • 拒绝新请求(返回 429/排队提示)
  • 或降级(用更小的 max_tokens、更低的优先级)

5.2 优先级调度(Priority Scheduling)

请求按 SLO 紧急性排序:快超时的请求插队(如 EDF——最早截止时间优先),避免”眼看要超时还在排队”。

5.3 请求级资源预留

调度器预估每个请求的资源需求(prompt 长度 → prefill 时长;输出长度 → KV 占用),预留而不是事后补救——vLLM 的 scheduler 本身就有按 token 数做预算的逻辑(第 3 章),SLO 感知调度在此基础上加”时间”维度。

5.4 过载保护(Overload Protection)

持续过载时:降并发 → 降 max-num-seqs → 拒绝 + 熔断。宁可拒一批请求,不拖垮全部请求——这是 goodput 思想在故障场景的延伸。

📌 关键点:SLO 感知调度的哲学——调度器做的是”预算管理”而非”尽力而为”。尽力而为在低负载时没问题,但一过载就全面崩盘;预算管理在过载时”牺牲少数保多数”,Goodput 反而更稳。


6. 解耦与 SLO 的天然契合

回到第 7 章主线——解耦为什么天然利好 Goodput:

混合架构解耦架构
TTFT 和 TPOT 共用一个资源池两个池各守一个 SLO
Prefill 突发直接冲击 Decode 尾部突发被 prefill 池隔离,Decode 尾部稳定
一个旋钮调两个目标每个池独立调参(TP、并发、batch)
资源按”峰值耦合需求”配置资源按各自 SLO 需求独立配置
  • vLLM 官方文档把”控制 tail ITL”列为 disaggregated prefill 的核心动机
  • DistServe 的 goodput 提升(7.4×)正是”解耦 + SLO 感知”组合的结果

💡 提示:理解这条因果链——解耦让”独立 SLO”成为可能,Goodput 让”独立 SLO”成为目标。没有 Goodput 视角,解耦只是”把进程拆开”;没有解耦,Goodput 优化在混合架构里处处受制。两者互为对方存在的理由。


7. 工程落地:SLO 监控与告警设计

7.1 该采什么指标

  • 分位点直方图:TTFT/TPOT/端到端的 P50/P90/P95/P99(别只存均值!)
  • 达标率:SLO 达标请求比例(Goodput 的分子)
  • 过载信号:队列深度、拒绝率、GPU 利用率

7.2 告警设计

  • 告警条件写在 SLO 达标率上(如”P95 TTFT > 2s 持续 5 分钟”),而不是均值
  • 分级:P90 超标(警告)/ P95 超标(严重)/ P99 超标(紧急)
  • SLO 预算(error budget):允许的累计不达标时间(如每月 1%),用于”发布/扩容”决策

7.3 压测与容量规划

  • 压测目标 = 找 Goodput 上限(第 4 节的方法)
  • 扩容触发 = Goodput 接近上限 + 趋势向上
  • 容量报告 = “当前峰值负载下,Goodput 余量 x%“——用 SLO 语言汇报,管理层才听得懂

📌 关键点:工程上最容易被忽视的一环——把 Goodput 写进容量规划和发布流程。团队常见的死法:上线看 QPS 涨了 20% 欢呼,实际上 P99 已经悄悄超了 SLO 一个月。指标选错了,优化方向全错。


📝 总结

  • Goodput = 吞吐 × SLO 达标率:把服务质量乘进吞吐,才是服务的真实产出
  • SLO 三要素:指标(TTFT/TPOT/端到端)× 分位点(P95/P99)× 阈值——缺一不可
  • 分位点而非均值:均值掩盖尾部,P99 成本远高于 P95,按需选择
  • SLO 感知调度:准入控制、优先级(EDF)、资源预留、过载保护——预算管理而非尽力而为
  • 解耦 ↔ Goodput 互相成就:独立 SLO 是解耦的动机也是解耦的红利
  • 工程落地:分位点直方图、达标率告警、error budget、Goodput 容量报告

🎯 自我检验清单

  • 用自己的话定义 Goodput?为什么”高吞吐低达标率”是虚胖?
  • 写出一个完整的 SLO 语句(三要素齐全),并指出”均值 SLO”错在哪
  • P95 与 P99 的资源成本差异?什么场景选哪个?
  • 如何压测出系统的 Goodput 上限?(画负载-延迟曲线说明)
  • SLO 感知调度的四种机制?“预算管理 vs 尽力而为”的区别?
  • 解耦为什么让”独立 SLO”成为可能?因果链是什么?
  • 监控里为什么必须存分位点直方图而不是均值?

📚 参考资料