11.08 SLO 与告警:从 IM 用户结果到错误预算
返回第十一卷 · 业务测量:11.01 · 分布:11.02 · 观测:11.03 · 压测与容量:11.07
11.08 SLO 与告警:从 IM 用户结果到错误预算
DeepTutor 八节初稿经技术与教学审阅后的静态课程。所有请求、设备确认、目标比例、预算和告警均为虚构纸上设计,未运行 Go、IM、监控、告警、部署或站点。当前 S2
/v1的正文非空且最多 6 UTF-8 B、原始 HTTP 请求正文最多 4096 B、同 ID 重复 409、非成员隐藏 404、200 accepted_in_memory仅表示本进程内存受理;未来 S3/v2的stored_in_teaching_db是提议且仍为 6 B,R9 6→9 B 待审。09.02 当前合同
一、先问用户得到什么,再给目标一个数字
“服务可用 99.9%”听起来明确,但谁在使用哪条功能?A 在两秒内得到发送受理回应、未来权威消息落库、B 的设备在一分钟内看到消息、离线 25 小时后补拉到历史,都是不同结果。11.01–11.03 已教我们起止事件、分母、分布与观测盲区;11.07 又教我们压测的成功点必须绑定合同。现在才开始讨论服务水平指标 SLI和服务水平目标 SLO。11.01 确认点与分母 · Google SRE:Service Level Objectives
本章先给未来个人实现的 S2 教学接口设计一张候选指标卡:从有权的 A 发起一次合法、非重复的 /v1 首发 POST,到 A 在 2 秒内完整收到 200 accepted_in_memory,算“好”。服务端若已内存受理,但响应在路上丢了,A 仍无法在 2 秒内确认,本指标按用户体验记“坏”;它不否认服务端可能已经受理,也不表示消息已持久或送达 B。09.04 响应丢失与未知
当前仓库没有正在运行的 S2 在线服务,2 秒与后文的 99.9% 都是待评审教学数值,不是已批准的生产承诺。未来 S3 的 stored_in_teaching_db 和 S5 的设备 ACK 必须有独立指标,不能为了让一个 200 比例好看,悄悄给“交付成功”换定义。07.12 确认矩阵
二、SLI 卡片:分子、分母、时间窗和未知
把 S2 候选 SLI 写成一张可执行的分类合同,而不是“HTTP 成功率”:
| 字段 | 本章纸上定义 | 为什么要写清 |
|---|---|---|
| 单位 | 一次有权、合法、非重复的首发请求尝试 | 同 ID 重试是另一尝试,不能冒充新消息 |
| 起点 | A 客户端开始发起该 POST | 不能只从服务端收到请求开始,漏掉网络等待 |
| 好事件 | A 在 2 秒内完整收到当前版本的 200 与 accepted_in_memory | 服务端拟写 200 不等于 A 收到 |
| 坏事件 | 进入该队列后 2 秒仍未达到好事件,包括超时/结果未知 | 不因服务端可能成功而删除用户的坏体验 |
| 不入组但另计 | 无效参数 400、同 ID 重试 409、非成员隐藏 404 | 正确拒绝不是本指标的合格首发机会 |
| 时间 | 按首发开始时间落入滚动 30 日窗口,观察满 2 秒后归档 | 不能按完成时刻混入旧请求,或提前判未完成者 |
上表是一种候选业务口径,不是所有 IM 必须采用的口径。若产品关心“同一用户意图最终是否确认”,应另定义以唯一意图为分母、包含状态查询与重试的指标;它和“首发请求体验”不能混算。400/409/404 虽不入本卡,也必须在拒绝/安全/客户端质量看板单列;若有权首发请求因服务故障意外返回 5xx 或断线,则按本卡算坏,不能改名“非合格”来缩小分母。11.01 尝试与唯一消息
滚动窗口的边界也要照顾观察期限。若在报告时刻 T 统计 [T−30 日,T) 中开始的尝试,最近 2 秒的项可能仍在等待,应延迟报告到它们归档,或清楚标“待决”,不能默认这些未完成者都成功。若窗口里没有一条合格机会,分母为 0,SLI 是未定义/无样本,不是 0% 或 100%。客户端埋点整体丢失时,甚至可能不知道有没有机会,须另报观测覆盖不足,不能把没有数据的图画成绿色。11.03 指标采集边界
三、SLI、SLO、SLA 是三个不同层级
SLI 是上述“好次数 ÷ 合格机会次数”的定量观测;SLO 是希望它在某观察窗口满足的目标;SLA 是与用户或客户形成、通常写明达不到目标后果的协议。一个团队可以先有 SLI 和内部 SLO,却没有对外 SLA;把纸上目标写成“SLA 保证”会把教学练习误变成外部承诺。Google SRE:SLI/SLO/SLA
给 S2 卡片一个仅供计算的候选 SLO:“滚动 30 日内,至少 99.9% 的合格首发尝试在 2 秒内收到内存受理 200。”这是事件比例目标,不是“P99 小于 2 秒”的同义句:P99 可能只从已完成请求里计算,遗漏超时、断线和待决;即使同一全量队列,99.9% 与 P99 的门槛位置也不同。目标值要由业务影响、历史观测、实现成本与负责人评审,不由课本代替审批。11.02 分位与缺失样本
未来 S5 可以另提一张不同的纸上卡:“起点时在线且有权的目标设备,与一条权威消息组成一个合格的消息×设备机会;在 60 秒内收到 B 设备按稳定消息 ID 发出的应用处理 ACK,算好。”为练习暂设目标 99%。B 本来离线 25 小时的消息不入这个“在线设备 60 秒”分母,而要有离线补拉指标;未知/无 ACK 到期按该卡算坏或标观测失效,不能按网关 Write 成功充当好。A 的 99.9% 与 B 的 99% 回答不同问题,不合并预算。11.06 TCP 与设备 ACK
四、错误预算:允许多少坏机会,已经花了多少
对“好比例 ≥99.9%”的事件式 SLO,允许的坏比例是 100%−99.9%=0.1%。假设滚动 30 日内已经归档了 100,000 次合格 S2 首发机会,纸上预算为 100,000×0.001=100 次坏机会。若实际 99,500 好、500 坏,好比例是 99.5%;坏机会超过预算 400 次,已经消耗了预算的 5 倍。这不是“差 0.4 个百分点所以没事”,而是对该目标失约的明确算式。Google SRE Workbook:Implementing SLOs
| 纸上卡片 | 合格机会 | 候选目标 | 允许坏 | 假设实际 | 预算结论 |
|---|---|---|---|---|---|
| S2 A 在 2 秒内收到内存受理 | 100,000 | 99.9% | 100 | 99,500 好、500 坏 | 超 400;消耗 5 倍预算 |
| 未来 S5 在线 B 设备 60 秒 ACK | 1,000 | 99% | 10 | 985 好、15 坏 | 超 5;消耗 1.5 倍预算 |
第二行的 1,000×(1−0.99)=10;1,000−985=15。它是另一确认层的教学样本,不能拿 S2 还剩多少预算去“抵消”B 的迟到。实际窗口可能有非整数预算,需要事先定义计数/比例与取整策略;本题特意选整数以聚焦概念。预算是决策工具,不是“允许故意丢 100 条”的许可,也不是每条用户消息丢失时可忽略的借口。若出现越权正文泄露等安全事故,更应按安全响应处置,不靠可用性预算开脱。Google SRE:错误预算政策
五、消耗速度:坏事件突然增多时别等到月底
消耗速度 burn rate把短窗坏比例与长期 SLO 允许坏比例比较。上面 S2 候选目标允许 0.1% 坏;若某虚构 1 小时里有 1,000 次合格机会、10 次坏,短窗坏比例 10/1,000=1%,消耗速度 1%/0.1%=10 倍。意思是若这种比例持续,预算会比目标均速快十倍耗尽;它不是“已经用了整月预算十倍”,也不说明这个 1 小时的 10 次恰好使整月 SLO 失约。Google SRE Workbook:Alerting on SLOs
低流量时要小心:某五分钟只有 1 次机会、1 次坏,坏比例是 100%,算出的 burn rate 很高,却缺少稳定样本;窗口没有机会时分母为 0,根本不能计算。可结合短窗快速发现、较长窗确认趋势、最小样本量、用户影响和观测覆盖率来设计通知等级。具体多窗口倍数与门槛必须经业务和运行验证,不能从教学“10 倍”直接复制为生产 pager 规则。Google SRE Workbook:多窗口告警
完成事件晚到也会改变窗口计数。若一条尝试开始于本小时最后一秒,须给它完整的 2 秒观察期限;未满时标待决,到期再归档,避免“刚开始就记坏”或“最后一分钟永远不统计超时”。B 的未来 60 秒 ACK 卡片同理。事件时间和采集时间不同还会引入迟到数据,报表需给更新时间和覆盖状态。07.11 事件时间
六、告警要让接收者知道现在能做什么
用户感知的症状适合触发需要人处理的告警,例如 S2 首发受理坏比例高且持续、未来 B 设备 ACK 迟到达到预设门。CPU、磁盘 busy、队列长度、GC 次数帮助定位和提前观察,但单个资源阈值不一定意味着用户受损;若无人知道如何行动,就不应把每次升高都变成呼叫。Prometheus 和 Google SRE 的告警实践都强调症状、可行动性与清楚的分工。Prometheus:Alerting Practices · Google SRE:告警与预算
| 告警字段 | S2 纸上候选写法 | 出现时的下一步 |
|---|---|---|
| 用户结果 | A 的合法首发未在 2 秒内收到 accepted_in_memory | 核对客户端/服务端同一请求及响应丢失 |
| 窗口与分母 | 短窗与长窗的合格机会、坏机会及待决/覆盖率 | 排除低样本或采集失效误报 |
| 责任与等级 | 明确值守角色、升级角色和响应时限 | 确认有人有权限与手册处理 |
| 诊断入口 | 入口到内存提交、队列、实例、错误类别 | 先分层,再看 CPU/池/网络 |
| 止损与停止门 | 有证据的限流/回退、观察拒绝与积压 | 防止“P95 好看了但更多用户被拒绝” |
一个 404 若是非成员目标被正确隐藏,是按合同工作的安全拒绝,不能塞进“服务异常 5xx”;同 ID 重试的 409 也应作为重试/用户体验单列。反过来,若安全授权检查失效而给了 200,HTTP 层的成功率可能更好,业务却更坏。因此还要有权限和数据完整性的独立验收/监测,不能让单一 SLI 覆盖一切。09.07 对象权限
没有数据不是健康。 若客户端全量埋点断了、合格机会无法进入指标,便无法计算这张 SLI;监控自身的采集覆盖和报表延迟要有独立通知。若只丢了服务端成功日志,但客户端仍完整记录了 2 秒内是否收到 200,本卡的用户体验分类可能还在,根因调查证据则减弱;两者要分别表达。11.03 黑盒/白盒
七、预算政策与版本演进也要写明
SLO 不是单人给某个百分比加粗。纸上卡片若要进入真实团队使用,需要产品、研发和运行负责人共同评审:目标是否代表用户体验、采集是否可靠、预算耗尽后怎样安排可靠性修复和发布、何时复核。Google SRE 的预算政策示例有“预算用尽时限制某些变更”等做法,但那是需要明确采纳的组织决策,本课程不把它自动套到任何系统。Google SRE Workbook:错误预算政策 · Implementing SLOs
版本迁移时更要防止“指标名没变、意思变了”。当前 S2 /v1 的 200 是内存受理;未来 S3 /v2 的 200 stored_in_teaching_db 若实现,是另一个成功点。可以为它新增带版本与确认点说明的 SLI,并保留旧窗口/旧客户端的解释,不能把历史 S2 的 200 自动算作“数据库存储成功”。R9 6→9 B 尚未批准,不能提前改变 /v1 的入组规则或正文上限。09.10 兼容矩阵
固定 openimsdk/open-im-server 提交 f6411a8a1a31d3df36f4c2b3ad28481a94141e1f 的 send.go 选定分支调用 MsgToMQ 后返回;另一 Mongo 消费路径调用 BatchInsertChat2DB。这两处只能提示发送返回与消费落库分属异步阶段,不能证明上游已承诺本章 SLI/SLO、生产者 ACK、设备结果或告警配置。公开项目的真实目标还需其正式合同、指标实现和运行证据。OpenIM 阅读地图
八、22 道分层练习:交两张指标卡与一条告警
先独立写分子/分母和算式,再展开反馈;最终提交 S2 当前接口的候选卡、未来 S5 的另一卡,以及只在可行动时才通知的设计。
基础 1–8:从确认点建立指标
1. `200 accepted_in_memory` 能当 B 设备收到的 SLI 吗?
不能。它只表示 A 侧本进程内存受理,未来设备 ACK 是另一结果。
2. SLI、SLO、SLA 各是什么?
SLI 是定量服务指标,SLO 是该指标的目标,SLA 是含后果的服务协议。
3. 服务端提交完成但 A 的响应丢失,本章首发体验算好还是坏?
若 A 未在 2 秒内收到完整 200,本卡按用户体验算坏;服务端结果另查。
4. 同 ID 重试得到 409,应直接当作本卡服务故障吗?
本卡按合法非重复首发尝试入组,重试另计;仍需观察其用户体验。
5. 非成员目标隐藏返回 404,说明服务不可用吗?
不说明。它是按合同的授权拒绝,须与意外失败分开。
6. 窗口里合格机会为 0,SLI 是 100% 吗?
不是。分母为 0 时未定义/无样本。
7. 客户端埋点全部丢失,图上没有坏事件,能报健康吗?
不能。机会数可能也丢失,需报观测覆盖不足。
8. 未来 S3 的 `stored_in_teaching_db` 与 S2 的 200 可混成同一成功点吗?
不能。它们承诺的阶段不同,须版本化和分开统计。
计算 9–16:预算与消耗速度
9. S2 候选 SLO 99.9%,允许坏比例多少?
100%−99.9%=0.1%。
10. 30 日合格机会 100,000 次,允许坏多少次?
100,000×0.001=100 次。
11. 实际 99,500 好、500 坏,SLI 多少?
99,500/100,000=99.5%,低于候选 99.9% 目标。
12. 上题超预算多少次、用了几倍预算?
超 500−100=400 次;用了 500/100=5 倍预算。
13. 未来设备卡目标 99%、机会 1,000,预算多少坏?
1,000×0.01=10 次。
14. 若 985 好、15 坏,设备卡预算怎样?
超 5 次,消耗 1.5 倍;不可由 S2 预算抵消。
15. 容许坏率 0.1%,短窗 1,000 次中 10 坏,burn rate 多少?
坏率 1%,消耗速度 1%/0.1%=10 倍。
16. 短窗 1 次机会 1 次坏可直接呼叫全员吗?
不宜仅凭高比例决定;样本小,需结合用户影响、长窗、覆盖率和预定动作。
评审 17–22:让告警有行动
17. CPU 90% 就必然触发用户故障 pager 吗?
不必然。先看用户症状/预算消耗,CPU 可作定位线索或容量预警。
18. 最近 2 秒尚未归档的首发尝试可提前算好?
不能。要完整观察 2 秒,标待决或延迟报告。
19. 没有设备 ACK,网关 Write 成功可以补成好事件吗?
不能。应用 ACK 未到期前待决,到期按定义算坏或标观测失效。
20. 一条可行动告警至少写什么?
用户结果、确认点、窗口/分子分母、覆盖率、负责人、证据入口与止损/升级步骤。
21. 错误预算耗尽必须自动停掉所有发布吗?
不是课程自动规则;须由相关负责人共同批准预算政策、例外和复核门。
22. 固定 OpenIM 两处源码能证明真实 SLO 或告警阈值吗?
不能。仅支持所读异步边界,目标和规则需业务合同、指标实现与运行证据。
本章完成标准与后续路径
能从 A 的具体用户结果写出 SLI 卡片,区别首发尝试与重试、无样本与遥测丢失;手算两种确认点的预算与 10 倍消耗速度;解释何时告警可行动、为何旧新 200 不能混算,才算完成第一轮。所有数值是纸上候选,真实目标须由学习者在有权限的系统内先测量、再经业务与运行负责人评审。下一章11.09 过载与级联故障将用排队、重试和重连风暴分析故障放大。