【113.Python+AI】大模型服务的可观测性:Prometheus + Grafana监控你的推理服务

📖 文章简介: 本文系统讲解大模型推理服务的可观测性建设,解决"服务上线后变成黑盒,出问题靠用户投诉才发现"的运维盲区。文章从AI服务与传统Web服务的监控差异切入——除了延迟和错误率,Token生成速度、KV Cache水位、队列长度这些AI特有指标才是健康的晴雨表;随后给出完整的指标体系设计:五类核心指标(延迟分布TTFT/TPOT、吞吐Token生成速度、容量KV Cache使用率/GPU利用率、稳定性错误率/超时率、业务请求量按模型按调用方)的采集方法与告警阈值建议;落地部分讲透vLLM原生Prometheus端点的接入(/metrics直接挂载)、Grafana看板的Panel布局(四象限布局:流量-延迟-容量-错误)、以及六条保命告警规则的配置(P99延迟超标、KV Cache水位超80%、错误率突增、GPU掉卡、Token速度腰斩、队列积压);最后聊业务层观测的补充——成本统计与badcase采样的落地。配以Mermaid流程图展示从指标采集到告警触达的完整链路,适合把推理服务推上生产后需要7×24保障的工程师阅读参考。


在这里插入图片描述

🎬 个人主页: 源码骑士

专栏传送门: 《Android开发基础》《python基础课程》

⭐️热衷从源码视角拆解技术底层原理,将复杂架构讲得通俗易懂


🎬 源码骑士的简介:
5年Android Framework系统开发经验,曾主导多项系统级性能优化专项
技术栈覆盖Android系统全链路(Binder/Handler/AMS/WMS/启动流程)及Java后端全家桶(Spring + MyBatis + Redis + Oracle)
累计产出原创技术文章100+篇,文章以流程图为特色,被读者评价为"看一篇胜过啃一周源码"


导入语

推理服务上线了,老板问:"服务稳吗?"你说:“挺稳的,没人报障。”——这不是监控,这是拿用户当人肉告警器。

AI服务的故障有个讨厌的特点:它很少"死透",更多的是"带病运行"。 显卡没挂、进程没崩,但延迟从500ms悄悄爬到3秒;KV Cache水位逼近红线,再有10个并发就要OOM;某个模型回答质量下降——这些问题用户能忍一两天才投诉,等你看到时已经烧掉了一周的体验分。

传统Web监控那套(QPS、错误率、CPU)照搬到AI服务上会失灵——AI服务有自己独特的生命体征:首字延迟、Token生成速度、KV Cache水位。这篇文章就把这套专属监控体系建起来:指标怎么选、怎么采、看板怎么摆、告警怎么配。


1 ~> AI 服务的五类核心指标

1.1 指标全景

类别指标健康参考线异常含义
延迟TTFT(首字延迟)P99 < 1s排队过长/前处理慢
TPOT(每token延迟)P99 < 100ms算力不足/显存换页
吞吐Token生成速度(tokens/s)基线±20%腰斩=严重降级
容量KV Cache使用率< 80%逼近OOM
GPU利用率/显存利用率60~90%过低=浪费,100%=过载
稳定性错误率/超时率< 0.5%引擎异常
业务请求量(按模型×调用方)趋势观测突增=容量预警

1.2 两个AI特有指标要理解透

TTFT(Time To First Token,首字延迟):
  用户发送 → 看到第一个字蹦出来的时间
  组成:排队时间 + prompt预处理(prefill)时间
  → 它直接决定用户觉得"卡不卡",是体验第一指标

TPOT(Time Per Output Token,逐token延迟):
  第一个字之后,每个字的间隔
  决定回答"流得快不快"
  → TTFT管第一印象,TPOT管全程体感

一个服务可以TTFT漂亮但TPOT拉胯(首字秒出、后面一个字一个字挤)——两个指标分开看,才能定位问题在prefill阶段还是decode阶段。


2 ~> 采集:vLLM 原生支持,一行接入

第108篇部署的vLLM自带Prometheus端点,接入成本几乎为零:

# prometheus.yml
scrape_configs:
  - job_name: vllm
    scrape_interval: 15s
    static_configs:
      - targets: ["gpu01:8000", "gpu02:8000"]   # 所有vLLM实例
vLLM原生暴露的关键指标(直接可用):

vllm:time_to_first_token_seconds   → TTFT分布
vllm:time_per_output_token_seconds → TPOT分布
vllm:gpu_cache_usage_perc          → KV Cache水位(第111篇的那本账!)
vllm:num_requests_running          → 正在处理的请求数
vllm:num_requests_waiting          → 排队长度(积压预警)
vllm:request_success_total         → 成功计数(算错误率)

自建网关(第109篇)补充业务维度指标:

# 网关层埋点:按模型×调用方记账
from prometheus_client import Counter, Histogram

REQ_COUNT = Counter("gateway_requests_total", "请求数",
                    ["model", "caller"])
REQ_LATENCY = Histogram("gateway_latency_seconds", "端到端延迟",
                        ["model"])

# 在处理函数里打点
REQ_COUNT.labels(model=req.model, caller=caller["owner"]).inc()

分工原则:引擎指标看"机器健不健康"(vLLM端点),业务指标看"服务好不好用"(网关埋点)——两层都要有,缺一层就是半个瞎子。

2.1 监控链路全景

数据源

vLLM /metrics
引擎指标

网关埋点
业务指标

node_exporter
GPU/主机指标

Prometheus
15s周期抓取

Grafana 看板
四象限布局

Alertmanager
告警规则引擎

钉钉/邮件/电话
分级触达


3 ~> Grafana 看板:四象限布局

看板不是指标的堆砌,是排障动线的预设。推荐四象限布局,一眼扫完就知道问题在哪一层:

┌─────────────────────┬─────────────────────┐
│ ① 流量象限           │ ② 延迟象限           │
│ QPS趋势              │ TTFT P50/P99        │
│ 按模型分面的请求量    │ TPOT P99            │
│ 在线/排队请求数       │ 端到端延迟热力图     │
├─────────────────────┼─────────────────────┤
│ ③ 容量象限           │ ④ 错误象限           │
│ KV Cache水位         │ 错误率/超时率        │
│ GPU利用率+显存       │ 5xx按模型分布        │
│ Token生成速度        │ 故障转移次数         │
└─────────────────────┴─────────────────────┘

排障动线:先看④有没有错 → 再看②慢不慢
  → 慢了看③容量满没满 → 最后看①流量是否异常

四象限的设计逻辑:错误、延迟、容量、流量,刚好对应"坏了→慢了→满了→多了"四种故障模式——按这个顺序扫一遍,30秒内完成初判。


4 ~> 告警规则:六条保命线

# alert_rules.yml 核心六条
groups:
- name: llm_service
  rules:
  # 1. 延迟超标——体验红线
  - alert: HighTTFT
    expr: histogram_quantile(0.99, vllm:time_to_first_token_seconds_bucket) > 2
    for: 5m
    annotations:
      summary: "TTFT P99 超过2秒,用户体验受损"

  # 2. KV Cache水位——OOM前最后的预警(第111篇的账本)
  - alert: KVCacheHigh
    expr: vllm:gpu_cache_usage_perc > 0.8
    for: 5m
    annotations:
      summary: "KV Cache水位超80%,逼近OOM"

  # 3. 队列积压——容量不够的明确信号
  - alert: QueueBacklog
    expr: vllm:num_requests_waiting > 10
    for: 10m
    annotations:
      summary: "排队请求持续超过10个,考虑扩容"

  # 4. 错误率突增
  - alert: ErrorRateHigh
    expr: rate(gateway_errors_total[5m]) / rate(gateway_requests_total[5m]) > 0.01
    annotations:
      summary: "错误率超1%,引擎或网关异常"

  # 5. Token速度腰斩——"带病运行"探测器
  - alert: ThroughputDrop
    expr: rate(vllm:generation_tokens_total[10m]) < 0.5 * rate(vllm:generation_tokens_total[1h] offset 1d)
    annotations:
      summary: "Token生成速度相比昨日同期腰斩"

  # 6. 实例失联
  - alert: InstanceDown
    expr: up{job="vllm"} == 0
    for: 1m
    annotations:
      summary: "vLLM实例失联"

告警纪律两条:告警必须可行动(收到告警不知道该怎么办的,不如不配);分级触达(水位类发钉钉群、实例失联打电话——别让半夜的电话只为一条"水位75%"响起)。


5 ~> 别忘了业务层观测

技术指标之外,AI服务还要盯两件传统监控管不到的事:

1. 成本观测
   按 模型×调用方×日 聚合Token消耗(第110篇的账本)
   → Grafana加一张成本趋势Panel
   → 某调用方用量突增300%?先问是不是脚本写死了循环

2. 质量观测(badcase采样)
   每天随机抽1%的问答对入库,人工或LLM-as-Judge抽检
   → 指标全绿但回答变蠢的情况,只有这个能发现
   → 模型版本升级后必做对比抽检

一句话:技术指标保证"服务活着",质量观测保证"服务聪明"。 前者告警驱动,后者抽检驱动,两条腿缺一不可。


思考 && 总结

  1. AI监控有专属指标: TTFT管第一印象、TPOT管全程体感、KV Cache水位管OOM预警——照搬传统Web监控是半个瞎子。
  2. 采集成本极低: vLLM原生/metrics端点直接挂Prometheus;引擎指标看机器健康,网关埋点看服务质量,两层齐备。
  3. 看板四象限: 流量-延迟-容量-错误对应"多了-慢了-满了-坏了"四种故障模式,按动线30秒完成初判。
  4. 告警六条保命线: TTFT超标、KV水位、队列积压、错误率、吞吐腰斩、实例失联;可行动+分级触达是纪律。
  5. 别忘业务层: 成本Panel防账单失控,badcase抽检防"指标全绿但回答变蠢"——活着和聪明是两件事。

可观测性就位,本地部署板块的所有零件——Ollama、量化、llama.cpp、vLLM、网关、多模型路由、显存管理、监控——全部到齐。下一篇是板块实战:把它们组装成一个"自用模型API平台",Ollama+vLLM+Nginx统一对外服务。


结尾

各位小伙伴,本文的内容到这里就全部结束了,源码骑士在这里再次感谢您的阅读!

源码骑士 — Android Framework & 全栈开发

👀 关注:跟博主一起从源码视角深耕底层原理,见证每一次成长

❤️ 点赞:让优质内容被更多人看见,让知识传递更有力量

收藏:把核心知识点存好,在需要时随时查、随时用

💬 评论:分享你的经验或疑问,评论区一起交流避坑

🔄 一键四连:不要忘记给博主"一键四连"哦!

🗡️ 寄语:技术之路难免有困惑,但同行的人会让前进更有方向

结语:没有监控的服务是在黑夜里开车——仪表盘亮起来的那一刻,你才从"祈祷不出事"变成了"知道自己在哪"。不要忘记给博主"一键四连"哦!

更多推荐