推理服务该盯哪些指标:一张诊断映射表
推理服务上线后最难的不是没监控,是有一堆监控但故障发生时不知道看哪个。这篇给一张诊断映射表:指标怎么动,问题就在哪儿。
验证截至 2026-10-21。指标名取自 vLLM 原生 Prometheus 端点;阈值与诊断映射综合自公开运维实践文章,文中已区分"原生指标"与"经验阈值",后者需按自身 SLO 调整。
环境与版本
- 适用对象:vLLM(其他引擎指标名不同,但诊断逻辑通用)
- 数据源:引擎自带
/metrics端点 +dcgm-exporter(GPU 层)+node-exporter(宿主机层)+ 网关层 - 前提:引擎必须先能吐指标。纯黑盒跑推理、不打日志不暴露端点的,装什么监控都救不了
为什么传统监控在这里失灵
传统微服务看 CPU、内存、网络 I/O、HTTP 状态码四件套。在 GPU 集群上你会遇到三种解释不了的现象:
- GPU 利用率长期 100%,但服务其实在空转等待
- 显存显示占满 95%,但你不知道这是健康还是马上要 OOM
- QPS 才 5,显存突然爆掉,容器被内核杀掉
根因是 LLM 的计算模式不同:prefill 吃算力,decode 吃显存带宽,KV cache 动态伸缩。所以指标集必须换一套。
另外,看 GPU 利用率建议用 DCGM 的 Duty Cycle 而不是 nvidia-smi 那个瞬时值——后者波动大,容易误判。
四层立体结构
从上到下要打通四层,缺一层就定位不到底:
| 层 | 数据源 | 关键指标 |
|---|---|---|
| 业务网关 | 网关 / 代理 | 租户配额、RPM/TPM 限流(429)、上游熔断率 |
| 推理引擎 | vLLM /metrics | KV cache 水位、排队数、TTFT、TPOT |
| GPU 硬件 | dcgm-exporter | SM 利用率、温度功耗、XID 错误 |
| 宿主机 | node-exporter | CPU 软中断、PCIe 带宽、共享内存 |
日志和链路追踪是另两层,不能省:日志用来查"哪次请求用了多少 KV cache、哪个长上下文触发了批处理等待";链路追踪用来回答"一次慢响应到底是卡在排队、模型计算还是后处理"。网关 + 多模型路由 + 后处理这种链式结构,没有 trace 就是黑盒。
五个最该盯的原生指标
1. vllm:kv_cache_usage_perc——显存的真实生死线
vLLM 启动时按 gpu_memory_utilization 把物理显存几乎整块划走,所以系统层面看到的显存占用永远是满的,没有参考价值。真正反映压力的是 KV cache 的实际占用百分比。
经验阈值(非官方标准,按自己的并发与上下文长度调):持续高于 75% 是黄色预警,说明并发或长文本在激增;高于 85% 就该紧急处理,此时极易触发请求抢占(preemption)或直接 CUDA OOM。
2. vllm:num_requests_waiting——容量指示灯
健康状态下应该持续为 0。大于 0 且持续上升,说明算力已到物理上限,后续请求全在排队。它同时也是做弹性扩缩容最合适的驱动信号——比 GPU 利用率更能反映"要不要加副本"。
3. TTFT(首 token 延迟)
用户点发送到屏幕上出现第一个字的时间。PromQL 取 P95:
histogram_quantile(0.95, sum(rate(vllm:time_to_first_token_seconds_bucket[5m])) by (le))
一定要在面向用户的边界上测——排队、检索、路由、工具调用、重试都会计入用户的体感,即使模型执行本身很快。
4. TPOT(每输出 token 耗时)
首字之后每个 token 的平均生成耗时。取倒数就是单请求的输出流速。参考口径:成年人阅读速度约 15–25 tokens/s,流速低于 10 tokens/s 时用户会明显感到"打字机卡壳"。
5. 投机解码的接受率
如果开了投机解码(MTP、草稿小模型等),必须同时看 spec_decode_num_accepted_tokens_total 和 spec_decode_num_draft_tokens_total,算接受率 = accepted / (accepted + draft)。接受率长期低于 50% 说明草稿模型猜得很差,此时投机解码不是在加速,是在白烧显存带宽和算力。
诊断映射表
这张表是监控大盘的操作手册,建议直接贴在图表旁边——凌晨三点被叫醒的人不需要重新推一遍排队论。
| 现象 | 指向 | 下一步查什么 |
|---|---|---|
| TTFT 高、TPOT 正常 | 上游问题 | 排队深度、prefill 压力、准入控制设置 |
| TTFT 正常、TPOT 高 | decode 侧受限 | batch 占用率、KV cache 水位、是否降频 |
| 两者同时升高 | 容量耗尽 | 加显存或加副本,调参已经没用 |
| 吞吐持平、延迟上升 | 已越过饱和拐点 | 在尾延迟崩溃前降载或扩容 |
DCGM_FI_DEV_XID_ERRORS ≠ 0 | 驱动或硬件级掉卡 | 立即摘除节点 |
只采延迟指标不采容量信号,你得到的看板只会告诉你"慢",说不出"为什么慢";反过来只采容量信号,则什么都解释得了但什么都证明不了。
告警怎么设
两条原则:
按 SLO 预算的消耗速度告警,而不是按裸阈值穿越告警。 这样 p99 的一次抖动只在该报警的时候报警,避免告警疲劳——见过最糟的情况是告警群 99+ 未读,真故障没人理。
技术告警用硬阈值立即触发,质量告警用软阈值转人工确认。 质量类指标噪声大、误报代价高,比如负反馈率环比涨 20%、LLM-as-judge 评分掉 0.1 以上,这类更适合转人工确认而不是自动触发。
一些常见参考阈值(来自公开实践,务必按自身 SLO 改):TTFT P99 > 2 秒、TPOT P99 > 100ms、队列等待 P99 > 5 秒、KV cache > 85%、显存 > 90%、错误率 > 1%。
成本侧建议单独设一路:单租户或单接口的 token 消耗按小时环比突增数倍就告警,这可能是滥用,也可能是 Agent 死循环在烧钱。
两个容易漏掉的坑
GPU hang。 进程活着、端口通、但 CUDA 死锁,健康检查全绿。解法是在探针里定时发一次极小推理,超时未响应就摘除实例重启。
"不报错但变笨"。 模型更新后技术指标完全正常,输出质量却退化了。这类只能靠质量侧监控发现:golden case 定期回归 + LLM-as-judge 抽样评分 + 输出长度分布突变检测。所以日志里每一条请求都要带上模型版本、prompt 版本和 trace id——没有版本标记的日志,出事时无法归因。
上线前必须演练的三件事
1. 过载行为:压到超过容量,看返回的是干净的 429 带重试提示、超时、还是半个响应;同时确认多个服务同时重试不会形成更大的流量尖峰
2. 故障转移:压测中途停掉一个 worker 或摘掉一张卡,确认控制面能检测到、停止向故障副本导流、并按设计恢复;同时定义哪些故障允许降级到小模型
3. 更新与回滚:即使模型版本没变也要完整演练一次——权重审批、兼容性检查、预热、健康检查、流量切换、回滚。固定模型与运行时版本,可变名会让事故无法复现;重要服务用金丝雀或蓝绿
边界与坑
- 不要把 prompt 原文默认写进日志,用可配置的保留期、脱敏和访问控制
- 每次部署记录模型 digest、引擎版本、量化方式、tokenizer、配置和硬件,缺一项就复现不了
- 有人看才有意义:告警接收人、恢复时间目标、升级路径要事先定好
常见问题
Q:显存一直显示占满,正常吗?
正常。vLLM 启动时就按比例把显存划走了,要看 KV cache 的实际占用百分比而不是系统显存。
Q:GPU 利用率高是不是好事?
不一定。高利用率配高延迟没有意义;严格交互 SLO 下低利用率也可能是合理的。要把利用率和延迟、吞吐放在一起看。
Q:开了投机解码一定更快吗?
看接受率。低于 50% 就是在浪费显存带宽。
Q:进程在、端口通,为什么还是不通?
可能是 CUDA 死锁。用小推理探针检测,别只做端口健康检查。
参考与延伸
- Xinference《Production LLM inference checklist: 8 tests before launch》——上线前八项检查的主要来源
- vLLM 官方 Prometheus 指标文档与社区 Grafana 看板模板
- 公开运维实践:vLLM 核心指标解读、四层监控架构与告警阈值速查表(阈值为经验值,非官方标准)
- 指标定义与诊断映射:多家推理服务监控实践整理,与 NVIDIA 推理基准的 TTFT/TPOT 口径一致