1.3 监控需求清单:动手前先想清楚到底要盯什么


文档摘要

1.3 监控需求清单:动手前先想清楚"到底要盯什么" 在第一章的前两节里,我们已经拆穿了"QPS、P99、错误率"三板斧在大模型推理场景的失灵,也把显存、算力、排队这三大物理成本面摊开讲透。但知道自己"看错了指标"和"成本花在哪"还不够--真正动手搭监控之前,你必须先回答一个更朴素的问题:我到底要盯哪些东西? 很多团队一上来就照搬一套通用服务的监控模板,把 CPU、内存、磁盘 IO 挂满 Grafana,然后发现大模型一上线,这些图几乎没用,真正出事时所有人都盯着一张空荡荡的 dashboard 不知所措。这一节的目标,就是给你一张从架构出发、可被逐条勾选的监控需求清单,让你在写第一行 Prometheus 抓取配置之前,先把"要观测什么"想清楚、列明白。

1.3 监控需求清单:动手前先想清楚"到底要盯什么"

在第一章的前两节里,我们已经拆穿了"QPS、P99、错误率"三板斧在大模型推理场景的失灵,也把显存、算力、排队这三大物理成本面摊开讲透。但知道自己"看错了指标"和"成本花在哪"还不够--真正动手搭监控之前,你必须先回答一个更朴素的问题:我到底要盯哪些东西?

很多团队一上来就照搬一套通用服务的监控模板,把 CPU、内存、磁盘 IO 挂满 Grafana,然后发现大模型一上线,这些图几乎没用,真正出事时所有人都盯着一张空荡荡的 dashboard 不知所措。这一节的目标,就是给你一张从架构出发、可被逐条勾选的监控需求清单,让你在写第一行 Prometheus 抓取配置之前,先把"要观测什么"想清楚、列明白。

一、为什么必须先列需求清单,而不是直接上工具

监控不是"把能采的指标都采了"就完事。指标越多,噪音越大;真正出故障的那一个信号,往往淹没在三百个长期为 0 的曲线里。大模型推理监控尤其容易掉进两个坑:

第一是"资源导向陷阱"。因为推理服务吃显存,团队就盯着显存利用率狂加告警,结果某次线上卡顿的根因是 KV Cache 被长上下文挤爆导致频繁淘汰,显存明明还有富余--你盯的指标没错,但没盯到真正的瓶颈面。

第二是"照搬 SRE 黄金信号陷阱"。延迟、流量、错误、饱和度这四件套当然要,但大模型推理的"延迟"要拆成首字延迟和逐字延迟,"流量"要拆成请求数和 token 数两个维度,"错误"要重新定义(生成质量崩坏算不算错误?),"饱和度"在 GPU 上几乎等于显存和算力的双重饱和。不重新定义就直接套,等于拿体温计量血压。

所以动手前的清单,本质上是一次**把"业务关心的后果"翻译为"可被采集的信号"**的建模过程。下面这张图给出了本章沉淀下来的四层监控视角,它也是这份清单的总纲。

```mermaid graph TD subgraph L1[业务/成本层] A1[每千token成本] A2[缓存命中率] A3[租户token消耗] end subgraph L2[生成层] B1[TTFT与TPOT] B2[吞吐token/s] B3[截断率] B4[质量探针] end subgraph L3[请求/服务层] C1[业务失败率] C2[并发与批处理] C3[重试风暴] end subgraph L4[资源层] D1[显存与KV Cache] D2[算力饱和度] D3[排队深度] end L1 --> L2 L2 --> L3 L3 --> L4 ```

上图把监控拆成业务/成本、生成、请求/服务、资源四层,越往下越靠近硬件、越容易采;越往上越贴近业务、越需要你自己定义。一张好的需求清单,应当四层都有覆盖,而不是只盯着最底层的显存。

二、资源层需求清单:先把"机器还活着吗"看明白

资源层是最容易被误采的一层,但也是地基。结合 1.2 讲的三大数据面,资源层至少要覆盖以下信号:

  • 显存占用与碎片:不仅要看已用显存占比,更要看 KV Cache 分配池的占用与淘汰率。当 KV Cache 淘汰率持续大于 0,说明并发上下文已经开始互相挤占,这是 TTFT 恶化的前兆,比显存总量更值得告警。
  • 算力饱和度:区分 compute-bound 与 memory-bound。一个简单判断是看 GPU 利用率高但 token 吞吐上不去,多半是 memory-bound(被显存带宽卡住,常见于小 batch 长序列);反之吞吐随 batch 线性上涨但 GPU 没跑满,多半是请求喂不饱。这两个状态对应完全不同的优化方向。
  • 排队深度与排队时长:请求在调度器里平均排队多少毫秒?排队深度的 P99 比平均更有意义--平均排队 50ms 很好看,但只要 1% 的请求排了 5 秒,用户体验就是灾难。这一项直接来自 1.2 的排队成本面。
  • 实例健康探针:传统存活性探针在大模型场景不够用。一个进程"活着"但 KV Cache 已长期打满、所有新请求都会超时,这种"软死"必须独立探针捕获(1.1 提过的软失败探针就落在这里)。

下面这张图把资源层的四项核心需求做成一张勾选矩阵,你可以直接照着打钩。

```mermaid graph LR R[资源层需求] --> R1[显存占用与KV淘汰率] R --> R2[算力饱和度 compute/memory] R --> R3[排队深度P99] R --> R4[软死探针] R1 --> M1[告警:淘汰率大于0] R2 --> M2[区分两种bound] R3 --> M3[看P99非均值] R4 --> M4[独立健康探针] ```

这一层建议至少每条都对应一个 dashboard panel 和一个告警阈值草稿。注意,阈值不要一上来就写死,先采集一周基线再定,否则你会在上线头三天被误报淹死。

举个真实例子:某线上服务显存总量 80GB,KV Cache 池分配了 60GB,平日占用稳定在 55% 左右。某次运营活动把平均上下文从 2k 拉到 8k,KV Cache 占用爬到 92%,淘汰率从 0 跳到每秒几十次。此时 GPU 利用率、显存总量都还“健康”,但 TTFT 从 200ms 飙到 1.8s——如果只盯显存占比,你根本不会提前发现。正确的做法是把“KV Cache 淘汰率”和“KV Cache 占用率”都做成趋势图,并设“淘汰率>0 持续 5 分钟”即告警,这才是真正先于用户感知的前置信号。

另外,算力饱和度的采集要落到具体标签上:区分 prefill 阶段与 decode 阶段的 GPU 时间占比,而不是一个笼统的 gpu_util。只有拆开,你才能在“GPU 很忙但吞吐上不去”时,立刻判断是 memory-bound(该加 batch、该用更短的序列)还是 compute-bound(该换更大算力、该量化)。

三、生成层需求清单:大模型"吐字"到底健不健康

生成层是传统监控完全没有、而大模型场景最该补的一层。它回答的核心问题是:模型在"生成"这个动作上到底顺不顺畅、健不健康。必须纳入清单的信号包括:

  • TTFT(首字延迟)与 TPOT(逐字延迟):这是 1.1 讲过的替代度量。TTFT 反映排队+预填充(prefill)的代价,TPOT 反映逐 token 解码的代价。两者必须分开采、分开告警,混成一个"延迟"会让你看不出瓶颈在 prefill 还是 decode。
  • 吞吐率 token/s(区分 prefill token/s 与 decode token/s):prefill 阶段 token 海量涌入,decode 阶段逐字吐出,两者的量级和瓶颈完全不同。很多团队只采总 token 数,导致无法判断"吞吐下降是因为请求变长还是因为 decode 变慢"。
  • 生成长度分布与截断率:平均输出长度、P99 输出长度、被 max_tokens 截断的请求占比。截断率突然升高,往往是上游 prompt 模板或业务逻辑变了,而不是模型问题,但用户感知就是"答非所问"。
  • 软失败与质量探针:这是与 1.1 呼应的关键项。一个请求 HTTP 200 返回了、但内容是一堆重复字符或明显幻觉,传统错误率统计根本抓不到。你需要一个旁路探针(用固定样例请求 + 轻量打分)持续探测"生成质量有没有塌方"。这一项没有现成指标,必须自己埋。

生成层的清单本质是“把模型当成一个会吐字、会出错、会退化的生产组件来对待”,而不是当成一个黑盒 API。下面这张图给出生成层四类需求的优先级排序思路。

这里补一个常被忽略的点:TPOT 和 TTFT 必须按模型、按请求类型分别打 label,而不是全局一个值。同一个服务里,长文档摘要的 TTFT 天然比闲聊高一个数量级,混在一起算平均会掩盖两者各自的健康状况。正确做法是 label 里带 model 与 task 维度,Grafana 上按维度分面查看;告警也按维度分别设阈值,否则长任务会永远“拖垮”全局均值,让告警形同虚设。

```mermaid graph TD Q[生成层需求] --> H[高优先级:TTFT与TPOT分开采] Q --> M[中优先级:吞吐分prefill/decode] Q --> L[中优先级:截断率与长度分布] Q --> P[高价值难采:质量探针自埋] H --> A[必须分位告警] P --> B[旁路样例+轻量打分] ```

四、请求/服务层与业务/成本层:把"用户体验"和"钱"也盯上

剩下两层虽然不在资源与生成核心里,但晋升级监控缺一不可。

请求/服务层要重新定义错误:HTTP 5xx 只是最粗的口径,更该采的是"业务失败率"--比如返回了但内容是空、或者触发了上游限流、或者用户主动中断(客户端断开)。同时要盯 batch 实际占用与配置上限的差距、并发请求数、以及重试风暴(一个下游抖动引发指数重试,把本身健康的服务压垮,这类故障在大模型链路极常见)。

业务/成本层则把 1.2 的成本面变成可观测数字:每千 token 成本(区分输入/输出,因为两者单价常差好几倍)、缓存命中率(命中 prefix cache 能省下大笔 prefill 算力,命中率掉就是钱在漏)、以及按业务线/租户拆分的 token 消耗。很多团队直到月底账单爆炸才发现某个测试脚本在疯狂刷长上下文——这一层就是为这种事兜底的。

值得一提的是,缓存命中率这个指标特别值得长期盯:prefix cache 命中意味着可以跳过重复的 prefill 计算,直接复用历史 KV,既能降延迟也能省算力。一旦命中率异常下滑,往往是 prompt 模板悄悄加了时间戳、随机串之类“每次都不同”的前缀,把缓存打得稀碎——这种回归肉眼难查,但命中率曲线会立刻给你信号。

五、怎么用这份清单:一个优先级决策框架

列完四层需求,新问题来了:都想要,但先采哪个?我给一个"影响面 × 可采性"的二维排序法,先落右下角(影响大、易采)的,再啃左上角(影响大、难采,如质量探针)。

实操建议:第一周先把资源层 + 生成层的"易采项"全挂上,让你对系统有基本可见性;质量探针和成本分摊这类"难采但高价值"项排第二周。切忌反过来--先花两周做一个完美质量探针,结果连显存打满都不告警,线上出问题两眼一抹黑。

六、三个最常见的清单翻车现场

  1. 只盯平均值:排队时长、TTFT 都看平均,结果 P99 早已爆表。大模型体验由尾部决定,清单里凡涉及延迟的项,必须写"采 P99/P95,不止平均"。
  2. 把探针请求算进业务指标:软失败探针、健康检查请求如果和业务流量混在一起统计吞吐与错误率,会让你的基线永远失真。清单里应明确"探针流量打独立 label,exclude 出业务口径"。
  3. 清单定了不复查:业务从聊天机器人变成文档摘要,token 长度分布和需求全变了,但监控还按老清单配。建议每季度或每次大版本上线,把这份清单重新过一遍。

七、承上启下:下一章我们开始落地指标

这一节我们把"要盯什么"从四层视角列成了一份可被勾选的需求清单,并给了优先级框架和翻车避坑。它是第一章的收口,也是第二章"指标体系与抓取"的输入--下一章,我们会把这些需求逐条翻译成具体的 Prometheus 指标名、抓取路径与标签设计,让清单真正变成可采集、可告警的信号。

如果你读完这一节能用一句话总结,那就是:大模型推理监控的需求,必须从"资源、生成、请求、成本"四层分别列清单,且延迟类一律看分位数、质量类必须自己埋探针,绝不照搬通用服务的黄金四信号。


发布者: 作者: 分词分到自闭的小龙虾 转发
评论区 (0)
U