1. 先别急着接监控系统:推理延迟到底在盯什么
做AI模型推理服务的同学,大概率都经历过这种半夜惊醒的时刻:手机报警短信疯狂震动,爬起来一看——延迟超标了,但等你打开Grafana,指标已经自己恢复了,只能悻悻躺回去。或者反过来,指标图一路狂飙,但业务方反馈“还能用”,你根本分不清是该紧急处理还是继续睡。
我做了几年的模型推理服务运维,最大的感受是:延迟监控和报警这件事,难点不在“怎么监控”,而在“监控什么”和“报警怎么定”。如果直接把业务侧常用的“平均响应时间超过200ms就报警”这套方法论搬过来,大概率会被折磨到怀疑人生。
先说第一个核心认知:大模型推理服务的延迟,和传统Web服务的RT(响应时间)有本质区别。传统Web一个请求就是一个完整的事务,响应时间能直接反映用户体验。但大模型推理是流式生成的,一个请求可能是几百个token连续吐出来,用户看到第一个字的时间、看到完整回答的时间、请求在队列里排队的时间,这三个数字完全不同,也分别代表不同环节的健康度。
我建议先做一次指标盘点,把延迟拆成五个维度再谈监控:
- 首Token延迟(TTFT,Time To First Token):从请求发出到模型吐出第一个token的时间。这是用户能感知到的“响应速度”,也是最关键的业务指标。一般超过3~5秒,用户感知就会很差。
- Token生成速度(TPOT,Time Per Output Token):生成后续每个token的平均耗时,决定用户看完回答的总时间。通常用“每秒生成多少个token”来描述更直观。
- 端到端总延迟:从请求发起到最后一个token返回的总时长,等于TTFT加上所有token的生成时间之和,再算上网络传输等开销。
- 排队时长(Scheduling/Waiting Time):请求到达服务后,等待调度器分配GPU资源的耗时。排队时间过长往往意味着服务容量不够,或者并发策略配置不合理。
- 冷启动/扩容延迟:在自动扩缩容场景下,新实例从创建到真正能承接流量的耗时。如果经常触发扩容,但扩容半天起不来,延迟照样崩。
这五个维度,每个都要有独立的统计和监控规则,绝对不能混在一个“平均延迟”里。混在一起的结果就是:某次请求因为排队等了10秒,平均延迟从200ms被拉到1800ms,报警倒是触发了,但你根本不知道是排队、显存不足还是模型推理本身变慢,排查效率极低。
另外还要强调一点:延迟监控必须按模型、按版本、按部署环境(如在线服务、离线批量任务)分开打标签。如果你的服务是多模型混部,或者同一个模型还挂着几个版本做灰度,标签没分开的话,报警一到你连是哪个模型出问题都不知道。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 指标采集的三个层次:从日志埋点到分位数统计
确定要监控哪些指标后,下一个问题是:数据从哪里来?我在实际落地中把采集方案分成三个层次,不同阶段选不同方案,性价比最高。
2.1 第一层:请求日志的精准埋点
最基础的采集方式,是每个推理请求在处理时,把上面五个维度的耗时数据记录到结构化日志里。具体来说,我通常会在推理服务的网关层或代理层做统一埋点,而不是让每个模型服务自己上报。
埋点的关键字段,我的建议是最少包含这些:
json复制{
"request_id": "a0f8c1d2-...",
"model_name": "chat-7b-v3",
"model_version": "20240112",
"timestamp": 1705123456789,
"ttft_ms": 850,
"tpot_ms": 46,
"total_tokens": 386,
"end_to_end_ms": 18624,
"queue_wait_ms": 120,
"inference_ms": 18200,
"status_code": 200
}
这里有个容易被忽略的点:第一次请求和后续请求的耗时差异巨大。如果模型文件还没加载到GPU显存,第一次请求可能要吃十几秒甚至几十秒的冷启动延迟。所以我一般在埋点里加一个is_warmup字段,用于标记是否首次请求。如果不把这个单独拎出来,首个请求会被误判为性能严重劣化,导致误报警。
日志埋点的缺点很明显:它不是实时的。日志写到磁盘、采集器解析、写入存储,再到查询出来,通常有几十秒到几分钟的延迟。用来做事后分析足够,但用来做实时报警就不太够。所以它通常作为“指标存储”的补充,不单独承担报警职责。
2.2 第二层:框架内置指标的主动暴露
到大模型推理这个阶段,大部分主流推理框架已经内置了监控指标接口。比如vLLM、Triton Inference Server、TensorRT-LLM,都会暴露Prometheus格式的metrics端点,里面常见的有:
vllm:request_success_total
