SLI、SLO 与预算:定义的是用户结果,不是仪表盘颜色
一个"99.9% 可用"的仪表盘可能同时掩盖"任务永远排队"和"小租户全挂"两类用户受损。本页以异步文档导出为例,写准 SLI 的分子分母、推导错误预算与燃烧率,并用它们做发布与止损决策。SLI 是实际测量,SLO 是约定目标,SLA 还涉及对外义务与补偿,三者不能互换。Google SRE 的 SLO 实施章节强调从用户体验选择指标;下面的 99.9% 和阈值属于教学题设。
案例链路:HTTP 返回任务号,后台生成文件,用户下载。高级工程师要能写出准确的指标分子与分母;架构师要据此决定是否停止发布、投入多少恢复容量以及哪些租户需要单独保障。指标口径如何从质量场景推出,见质量属性必须描述场景。
分子分母:把"成功"定义到能唯一判定
导出链路至少有受理成功率、按时完成率、下载成功率和文件正确性。仅看 HTTP 202 会把永久积压的任务当成功;仅以已完成任务为分母会把永不完成的任务删除。定义"有效受理任务"为经过授权并持久化的请求;对于 60 秒完成目标,统计已经到达截止时刻的创建批次。到截止仍未产出、任务失败、输出校验不通过都计坏事件,不能因尚在运行就不入分母。
客户端主动取消、非法输入、零流量和采集失败需要分别定义。用户正确取消可以从完成 SLI 排除,但必须记录取消发生在什么阶段,不能把服务器过载导致的超时伪装成取消。没有样本时成功率未定义,不能填 100%;遥测断流需要单独报警与替代证据。按用户旅程计算时,重试多次最终成功可以算一次成功,内部每次尝试的失败率则用于诊断,两种分母都合理但回答不同问题。
带数字推导预算和燃烧率
题设为 30 天共有 12,000,000 个已到期的有效任务,按时且正确完成目标 99.9%。允许坏事件 12,000,000×0.001=12,000 个。实际坏事件 8,400,SLI 为 99.93%,还剩 3,600 个事件预算,即总预算的 30%。预算不是剩余可以停机的分钟数;只有时间型可用性且时间权重满足定义时,才能把 30 天的 0.1% 写为 43.2 分钟。
假设最近一小时 20,000 个到期任务中有 240 个坏事件,错误率为 1.2%,燃烧率为 0.012/0.001=12。若窗口内流量和错误率维持,消耗相同长度目标期预算的速度是基准的 12 倍。不能据此直接断言"剩余预算还能撑 60 小时",因为未来请求量、滚动窗口移出旧事件以及存量预算均会变化。对固定月窗,按此小时流量推算,3,600 个剩余额度约够 15 小时;这是恒定流量的外推,不是保证。
告警也不能只在错误率超过 0.1% 时立刻寻呼。短小波动可能很快恢复,低流量下一个坏事件可造成很大比例。Google SRE 多窗口燃烧率告警讨论检测速度、精确率与复位速度的取舍。教学策略可让较长窗口确认持续风险,较短窗口确认现在仍在燃烧,再按影响升级;具体倍数要用本服务历史重放校准。
故障时序:为什么聚合会掩盖用户受损
租户甲占 99% 流量,错误率 0.01%;租户乙占 1%,错误率 8%。加权全局错误率为 0.99×0.0001+0.01×0.08=0.000899,全局 99.9101% 达标,乙却只有 92%。全局 SLO 可以衡量整体损失,但不能替代关键租户或地域的分层目标。不要把每个用户 ID 直接做指标标签;分层指标可按有限套餐、区域与工作负载类别组织,个体调查通过受控日志或账本完成。
再考虑 t0 任务被接收,t30 worker 崩溃,t60 任务截止,t90 重新完成。t60 应产生一次坏完成事件,t90 是恢复成功且超时 30 秒,不能回写成原本按时。重放监控事件要有稳定任务身份,防止同一个失败被记多次。指标聚合系统的计数不一定具有业务账本级去重,因此要求强审计时应从任务事实表派生周期报告,并和在线指标对账。
两种发布决策
方案 A 在剩余预算不足 25% 时冻结有风险发布,仅允许修复与低风险变更;方案 B 按各用户旅程当前燃烧率、事故状态及变更关联动态决定。A 简单、可解释,但月底偶发已结束的事故可能使后续必要改进停滞;B 更贴近当前风险,但需要可靠指标、清晰责任人与例外记录,否则容易人为放宽。发布门槛的三态判定与例外治理,见从愿景转成架构适应度检查。
本例尚余 30%,但当前正在 12 倍燃烧,应先止损而不是等待预算跌破阈值。冻结也不是禁止所有代码变化:已确认根因的修复仍需风险评估与小批验证。对"计算便宜但文件内容错误"的问题,正确性可以是独立硬门槛,不能由良好延迟分数抵消。错误预算用于支持业务与工程共同决策,不是惩罚团队或宣称每次发布的事故概率。
可重复纸面实验与产物
在本主题目录执行:
python3 labs/quality_models.py slo该脚本仅做确定性计算,不连接生产。预期输出 allowed=12000, remaining=3600, burn=12,全局加权错误率 0.000899。先手算再对照;把目标改为 99.95%,允许事件减为 6,000,原有 8,400 坏事件已超预算 2,400——提高目标不会自动提高服务质量,只会更快耗尽预算。完整脚本与各算例共用。
第二步重算甲乙分布,比较全局与分组判定。第三步列出 10 个样例任务,包含未截止、按时、超时后恢复、取消、重复事件各类,逐项判断是否进入分子和分母。预期同一份事实数据在正确口径下得到唯一结果;若两个评审者分歧,应修正事件定义,不能先平均两人的分数。脚本通过只证明算术自洽,不证明线上采集无缺失。
提交 SLI 契约、样本分类表、预算计算、告警条件及发布例外记录。运行态还需导出原始计数、采集间隔、窗口对齐和查询表达式。遇到滚动窗口,记录当前评价时刻;跨窗口比较不同累计量会制造虚假的预算变化。
预算窗口与告警判定:自然月、滚动窗与最小事件数
同一句"本月还剩 30% 预算",在自然月和滚动 30 天两种窗口下不是同一个量。自然月窗在每月 1 日重置,允许量固定等于当月事件数乘容许失败率;滚动窗每天都移出 30 天前的旧事件,允许量与剩余量随流量变化。自然月窗的 3,600 是"允许 12,000 减已坏 8,400"的剩余量,滚动窗的 15,000 是按 1,500 万事件重算的允许量——两个数字口径不同,直接比较会制造虚假的松紧变化。
固定自然月窗的计算已在正文给出:12,000,000 个到期任务、99.9% 目标、允许 12,000、已坏 8,400、剩 3,600。滚动窗的允许量必须用最近 30 天的实际事件数重算:若服务近 30 天有 15,000,000 个到期任务,允许坏事件是 15,000,000×0.001=15,000,与固定月窗的 12,000 无可比性。报告预算时必须同时写窗口定义、事件分母与评价时刻。
告警判定不能只看燃烧率。低流量下一个失败事件就能把比例放大:一小时 200 个请求、1 个坏事件,错误率 0.5%,燃烧率 0.005/0.001=5,若按静态阈值寻呼,会为一个事件叫醒值班。教学规则要求每个窗口先有最小事件数(本例 1,000),不足时输出"证据不足",由业务影响或更长窗口补充,而不是当作通过或失败。长窗口确认持续风险、短窗口确认仍在燃烧,二者都满足才升级;这是策略选择,倍数要按本服务历史重放校准。
执行 python3 labs/quality_models.py windows:输入目标 99.9%、最小事件数 1,000,分别判定 20,000 事件坏 240(燃烧率 12)、200 事件坏 1、0 事件坏 0。预期输出 STOP、INSUFFICIENT_EVIDENCE、INSUFFICIENT_EVIDENCE。脚本只做确定性判定,不重放真实监控;历史重放与误报率测量本轮未运行。
两种策略的真实取舍:A 固定百分比阈值,简单但低流量误报、高流量迟钝;B 多窗口燃烧率加最小事件数,贴合风险但需要可靠计数与历史重放证据,规则维护成本更高。可组合为分层:资源饱和类继续用固定阈值做容量预警,用户结果类走 B,但两类都不能把"无样本"填成 0。
架构师变化条件
把完成目标从 60 秒改为"用户可等待"的分层承诺:交互型 60 秒、批量型 10 分钟,分子分母按类别拆分,比较统一目标与分层目标的运营成本。把甲乙分布反转为乙占 60% 流量,全局与分组判定是否反转;再让遥测在事故中恰好断流,说明该小时数据按缺失处理而不是按 100% 成功补齐。每次变化都要重新回答:预算还能撑多久、该冻结谁、例外谁批。
闭卷验收
本页 8 道闭卷题收进了下方自测面板:先回忆,再展开参考答案与评分点,最后给三档自评。