第四章:监控体系搭建——四大黄金信号与实战工具链
监控体系这件事,我踩过的坑比走过的路还多。早期做推理系统时,我天真地以为只要CPU、内存、GPU利用率这些基础指标就够了。结果呢?线上模型推理突然变慢,排查了半天才发现是请求队列积压导致的。嗯,从那以后,我彻底理解了监控不是「看数据」,而是「看信号」。
今天咱们聊聊监控体系的核心——四大黄金信号,以及怎么用Prometheus、Grafana这套工具链把它落地。
4.1 四大黄金信号:延迟、流量、错误、饱和度
Google SRE 圣经里提过这四个信号。我个人习惯把它们叫做「系统体检四项」——缺一个,你都可能漏掉关键问题。
| 信号 | 含义 | 推理系统重点关注 |
|---|---|---|
| 延迟(Latency) | 请求从发起到返回的时间 | P50/P95/P99推理耗时、Token生成间隔 |
| 流量(Traffic) | 系统承载的请求量 | QPS、并发请求数、输入Token吞吐量 |
| 错误(Errors) | 请求失败或异常的比例 | 超时率、模型推理错误、OOM次数 |
| 饱和度(Saturation) | 资源被占用的程度 | GPU显存使用率、KV Cache利用率、请求队列深度 |
核心观点: 这四个信号不是孤立的。延迟升高,可能是流量突增导致的饱和度上升;错误率飙升,可能是延迟超时引发的连锁反应。我建议你画一张「信号关联图」,把因果关系理清楚。
4.2 指标采集:Prometheus 实战
Prometheus 是我最常用的监控采集工具。为什么选它?说白了,它天生适合微服务和AI推理这种动态环境。拉模式采集、多维标签、强大的PromQL,这些特性在推理系统中特别实用。
4.2.1 推理系统核心指标暴露
我习惯在推理服务中暴露以下几类指标:
- 请求级别指标:请求总数、成功数、失败数、延迟分布
- 模型级别指标:模型加载耗时、推理批处理大小、Token生成速率
- 资源级别指标:GPU显存使用量、显存碎片率、CPU负载
举个例子,用Python暴露自定义指标:
from prometheus_client import Histogram, Counter, Gauge, start_http_server
# 延迟分布:记录推理耗时
inference_latency = Histogram(
'model_inference_latency_seconds',
'Model inference latency in seconds',
buckets=[0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 5.0]
)
# 请求计数
request_total = Counter(
'model_request_total',
'Total number of inference requests',
['model_name', 'status']
)
# GPU显存使用率
gpu_memory_usage = Gauge(
'gpu_memory_usage_ratio',
'GPU memory usage ratio',
['gpu_id']
)
# 在推理函数中埋点
@inference_latency.time()
def predict(input_data):
request_total.labels(model_name='gpt-3', status='success').inc()
# ... 推理逻辑 ...
我的经验: 指标命名要规范。我吃过亏——指标名乱起,后期根本没法查。建议统一用 模块_指标名_单位 的格式,比如 model_inference_latency_seconds。
4.2.2 Prometheus 配置示例
scrape_configs:
- job_name: 'inference_service'
scrape_interval: 10s
static_configs:
- targets: ['localhost:8000', 'localhost:8001']
metrics_path: '/metrics'
relabel_configs:
- source_labels: [__address__]
target_label: instance
这里要注意,scrape_interval 别设太短。推理系统本身就有负载,采集太频繁反而影响性能。我个人习惯10-15秒一次。
4.3 可视化:Grafana 仪表盘设计
数据采集上来,得让人一眼看懂。Grafana 是我最顺手的可视化工具。你想想看,一个仪表盘上同时展示延迟、流量、错误、饱和度,问题在哪一目了然。
4.3.1 推荐仪表盘布局
- 顶部行:全局概览——QPS、平均延迟、错误率、GPU使用率
- 中间行:延迟分布——P50/P95/P99 折线图,配合热力图看趋势
- 底部行:资源饱和度——每个GPU的显存使用、请求队列深度
我曾经帮一个团队排查问题,他们的仪表盘堆了30多个面板,根本看不出重点。后来我帮他们精简到8个核心面板,问题定位时间从半小时缩短到5分钟。
4.3.2 关键查询示例
# P99 延迟查询
histogram_quantile(0.99,
sum(rate(model_inference_latency_seconds_bucket[5m])) by (le)
)
# 错误率
sum(rate(model_request_total{status="error"}[5m]))
/
sum(rate(model_request_total[5m])) * 100
# GPU显存饱和度
avg(gpu_memory_usage_ratio) by (gpu_id)
避坑指南: 我曾经犯过一个低级错误——用 avg 聚合GPU显存使用率。结果某个GPU爆了,平均值看起来还正常。后来我改用 max 或 topk,才真正捕捉到问题。记住:饱和度监控要看「最差情况」。
4.4 告警规则设计:别让告警变成噪音
告警设计是门艺术。我见过太多团队,告警规则写了一堆,结果全是噪音——没人看,看了也麻木。
4.4.1 告警分级
| 级别 | 触发条件 | 响应时间 | 示例 |
|---|---|---|---|
| P0(紧急) | 服务不可用、错误率>5% | 5分钟 | 模型推理全部超时 |
| P1(严重) | 延迟P99>2s、GPU显存>90% | 15分钟 | 某个GPU显存即将打满 |
| P2(警告) | 延迟P50>500ms、QPS突增50% | 30分钟 | 流量异常波动 |
| P3(通知) | 资源使用率趋势上升 | 日报 | 显存使用率周环比增长10% |
4.4.2 Prometheus 告警规则示例
groups:
- name: inference_alerts
rules:
- alert: HighErrorRate
expr: |
sum(rate(model_request_total{status="error"}[5m]))
/
sum(rate(model_request_total[5m])) > 0.05
for: 2m
labels:
severity: critical
annotations:
summary: "推理错误率超过5%"
description: "当前错误率 {{ $value | humanizePercentage }}"
- alert: GPUMemoryPressure
expr: max(gpu_memory_usage_ratio) > 0.9
for: 5m
labels:
severity: warning
annotations:
summary: "GPU显存使用率超过90%"
description: "GPU {{ $labels.gpu_id }} 使用率 {{ $value | humanizePercentage }}"
核心原则: 告警要「少而精」。我建议每个服务不超过10条告警规则。如果告警太多,说明你的系统稳定性有问题,或者告警设计本身需要优化。
4.5 本章知识体系总览
下面这张图是我自己梳理的监控体系架构,你可以对照着理解:
这张图把整个监控体系的链路串起来了。从四大黄金信号出发,经过Prometheus采集,再到Grafana可视化,最后通过告警规则形成闭环。你想想看,任何一个环节断了,监控体系就不完整。
最后说一句: 监控体系不是一蹴而就的。我建议你先从延迟和错误率两个信号开始,跑通Prometheus+Grafana这条线,再逐步加入流量和饱和度。迭代着来,比一开始就想做完美要靠谱得多。