← 返回目录
ap7.4实操⏱ 约 12 分钟

可观测性:平均值 10.5 秒,中位数 1.9 秒

以及 10 个 HTTP 200 里,0 个结果可用

🔎 最后验证 2026-08📚 来源:本节延迟分布与静默失败为 ECS 实测(2026-08,deepseek-chat,40 次调用 + 10 条截断样本,脚本与原始输出见本节代码)🧰 Python、DeepSeek API
为什么学这个

上线之后你会遇到一类最难受的问题:用户说"你们这个有时候特别慢",而你打开仪表盘,一切正常。

看这次实测——40 次真实调用:

  平均  10495 ms
  P50    1852 ms      ← 一半用户比这快
  P95   49487 ms      ← 20 个人里最惨的那个
  最大  49549 ms

平均值是中位数的 5.7 倍。这个"平均 10.5 秒"既不代表大多数人的体验(他们只等了 1.9 秒),也不代表最惨的人(他等了 49 秒)。它谁都不代表。

然后是更隐蔽的一类:10 次调用全部 HTTP 200,0 次结果可用。你的监控面板全绿。

💡 打个比方

"本店顾客平均等位 10 分钟"——听起来还行。

真相是:90 个人没等,10 个人等了 100 分钟。那 10 个人不会再来了,而你的平均数看不见他们。

一、别看平均,看分位数

  平均  10495 ms
  P50    1852 ms
  P95   49487 ms
  P99   49549 ms
  → P95 是平均值的 4.7 倍

平均值对长尾极其敏感:两次 49 秒的请求,就把 40 次调用的平均拉到了 10.5 秒。

该盯的三个数:

指标含义用途
P50一半用户比这快大多数人的真实体感
P9520 个人里最惨的那个告警阈值定在这里(用户抱怨来自这批人)
P99100 个人里最惨的那个容量规划、极端情况排查

告警阈值怎么定:先跑一周,拿到你自己的 P95 基线,阈值设在基线的 1.5-2 倍别拍脑袋定"超过 3 秒告警"——你的 3 秒可能是别人的 P50。

二、指标要能"切开",否则你只知道有人慢

  短输入(平均   11 tok,35 次)  P50   1214 ms   P95  49487 ms   最大  49549 ms
  长输入(平均  682 tok, 5 次)  P50   2112 ms   P95   2359 ms   最大   2359 ms

这个结果很有意思,而且和直觉相反:

  • 长输入的中位数确实更慢(2112 vs 1214 ms)——符合预期;
  • 最慢的那两次是短输入(49 秒)——长输入的最大值才 2.4 秒。

如果你只看到总体 P95 = 49 秒,然后想当然地去优化"长输入太慢",你就优化错了对象。这批长尾来自网络/排队抖动,不是输入长度。

所以指标必须能按维度切开:功能、模型、用户分层、输入长度、是否命中缓存、是否降级。光有一条曲线,你只知道"有人慢";切开之后才知道"慢的是谁"。

三、最危险的是"静默失败"

   ⚠️ 200 但不可用:「我要退货」 → {"category": "退款", "urgent": false, "reason": "用户明确表示要退货,属于退
   ⚠️ 200 但不可用:「快递没到」 → {"category": "物流", "urgent": true, "reason": "用户反馈快递未到,可能涉及物
   …
  HTTP 200:10/10   真正可用:0/10
  → 只监控 HTTP 状态码的仪表盘,这里全绿。

原因很朴素:max_tokens 给小了,JSON 被截断——每一条都在 reason 字段中间断掉。HTTP 层完美,业务层全挂。

这是 AI 产品特有的失败模式,传统 Web 监控完全看不见。至少要监控这四类:

静默失败怎么发现
输出被 max_tokens 截断检查 finish_reason == "length";校验器解析失败(ap3.2)
返回了内容但不符合 schema字段齐全性检查(ap3.5)
模型拒答 / 返回空空内容率、拒答率(ap5.4)
走了降级链路却没人知道degraded 字段(ap6.1)

核心动作:在你的日志里,ok(HTTP 层)和 business_ok(业务层)必须是两个字段。仪表盘上要看的是后者。

该记什么:一条结构化日志

{
  "ts": "2026-08-04T10:00:00+08:00",
  "request_id": "req_a1b2c3",     // ap7.1:和响应里的一致 —— 排查的钥匙
  "user_id": "u_123",             // ap6.4:配额与异常检测
  "feature": "qa",                // 按功能切维度
  "model": "deepseek-chat",
  "latency_ms": 1479,
  "ttft_ms": null,                // ap7.3:流式必记
  "in_tokens": 11, "out_tokens": 27,
  "cache_hit_tokens": 0,          // ap1.4:缓存命中率决定成本
  "cost_yuan": 0.000065,
  "ok": true,                     // HTTP 层
  "business_ok": true,            // ← 业务层:解析成功且字段齐全
  "degraded":               
              
   
   

这一条日志把前面六章串起来了:ap1.4 的缓存、ap1.6 的成本、ap6.1 的降级、ap6.3 的审核、ap7.1 的 request_id、ap7.3 的 TTFT。一行 JSON,把整个系统的健康状况装进去。

四个必配的告警

告警阈值建议为什么
业务成功率下跌低于基线 5 个百分点最重要——它涵盖了所有静默失败
P95 延迟上涨超过基线 1.5-2 倍用户抱怨的直接来源
单位时间成本异常超过日均 1.5 倍被刷、被注入、或缓存失效(ap6.4)
降级率上升超过 5%上游在出问题,你还没感觉到(ap6.1)

告警要能"值班时看懂":每条告警必须带上是什么、影响多少用户、该看哪个 request_id、上一次正常是什么时候一条只写"P95 告警"的短信,凌晨三点没有任何用。

🔧 动手做:给你的产品装上仪表(20 分钟)

  1. 跑本节代码,看平均 10.5 秒 vs 中位数 1.9 秒,和10 个 200 里 0 个可用
  2. 把日志改成上面那个结构(一行一条 JSON),尤其是 business_okrequest_id
  3. 算出你自己的 P50/P95/P99——用 ap1.6 的流水,一条 SQL 或者十行 Python。
  4. 加维度:至少能按 featuredegraded 切开看。
  5. 配四个告警,阈值全部基于你自己跑一周得到的基线,不是拍脑袋。
  6. 写一份告警响应手册:每条告警对应"先看什么、可能是什么、临时怎么止血"——写在告警消息里,不是写在别人找不到的文档里。

做到这里你应该有:结构化日志 + P50/P95/P99 + 可切维度 + 四个基于基线的告警 + 一份响应手册。

为什么:AP5 教你上线前怎么知道东西好不好,这一节教你上线后怎么知道。两者的区别是:评测集是你选的样本,线上是真实世界给你的样本——它一定会给你你没想到的东西(ap5.6 的回流就靠这些日志)。

而没有可观测性的产品,你只有两种状态:"看起来没事"和"用户投诉了"。中间那段——它正在慢慢变坏而你还有时间修——你完全看不到。

❓ 测验
40 次调用,平均延迟 10495ms,P50 只有 1852ms。为什么该用 P95 而不是平均值来设告警?
⚠️ 避坑监控自己会骗你——日志采样和维度爆炸

两个常见的"仪表盘失真":

① 采样把长尾采没了。流量大了之后大家会采样(比如只记 1%)。如果是均匀随机采样,P99 基本就废了——最惨的那 1% 很可能一条都没被采到。做法:错误和慢请求 100% 记录,正常请求才采样

② 维度爆炸。把 user_id 当成指标标签,一百万用户就是一百万条时间序列,监控系统直接被打爆(账单也是)。做法:高基数字段进日志,不进指标标签;指标标签只放低基数维度(feature、model、degraded、business_ok)。

第三个更朴素的坑:告警配了但没人看。上线前请做一次演练——手动触发一次告警,看它多久到达值班人手上没被验证过的告警链路,等于没有告警。

🤖 让 AI 帮你设计监控方案
我的 AI 产品是【描述】,现在的日志字段是【列出】,用的监控工具是【Prometheus/云监控/无】。请帮我:1) 设计结构化日志的完整字段(区分 HTTP 层成功和业务层成功);2) 列出该建的指标和它们的维度标签(注意避免高基数);3) 给出 P50/P95/P99 的计算方式和我该关注的基线;4) 设计 4-6 条告警规则,每条包含触发条件、严重级别、告警消息模板(要带排查线索);5) 写一份告警响应手册的模板,每条告警对应「先看什么、可能是什么、怎么止血」。
✅ 小结

可观测性三句话:看分位数别看平均(实测平均是中位数的 5.7 倍)指标要能按维度切开(长尾竟来自短输入)okbusiness_ok 必须分开(10 个 200 里 0 个可用)

下一节讲改动怎么安全地送出去:灰度与回滚——AP5 的门禁挡住了明显变差的改动,但有些问题只有真实用户能发现

下一节 → 灰度与回滚:改动上线的正确姿势
🔎 来源与核验· 3 条,点开核对
本节每个关键论断都对应一个可追溯的来源 —— 这是本课程"靠谱、不过时"的底线。
「40 次调用延迟实测:平均 10495ms、P50 1852ms、P95 49487ms、P99 49549ms,P95 为平均值的 4.7 倍」
📚 ECS 实测 observe.py 实验一(2026-08,deepseek-chat,并发 5)✓ 已核验 2026-08
「按输入长度分组:短输入(平均 11 tok)P50 1214ms、P95 49487ms;长输入(平均 682 tok)P50 2112ms、P95 2359ms——尾部最慢的是短输入而非长输入」
📚 ECS 实测 observe.py 实验二(2026-08)✓ 已核验 2026-08
「静默失败实测:max_tokens 设为 30 导致 JSON 被截断,10 次调用 HTTP 200 全部成功,业务可用 0/10」
📚 ECS 实测 observe.py 实验三(2026-08)✓ 已核验 2026-08
智图软件的赞赏码
都看到这了,打个赏呗!
接下来 · ap7.5
灰度与回滚:1% 灰度只是让少数人替你踩雷
继续读下一节 →