把 SLO 用起来:用错误预算设计可靠性目标与告警

SLO 与错误预算

“服务可用”常常只是一句模糊的期待:出了故障才发现用户受影响,告警又多到没人相信。SLO(服务等级目标)把这种期待变成可度量的承诺;错误预算则告诉团队,在不牺牲可靠性的前提下还能承受多少失败。

先把三个概念分开

概念 要回答的问题 一个接口示例
SLI 用户实际体验怎样 成功请求占有效请求的比例
SLO 希望保持到什么水平 最近 30 天成功率不低于 99.9%
错误预算 还能容忍多少失败 30 天内允许 0.1% 的有效请求失败

先写 SLI,再谈目标。一个常用的可用性 SLI 是:

1
可用性 = good_events / valid_events

valid_events 是应该被统计的请求,good_events 是满足体验条件的请求。条件不要只看 HTTP 状态码:下单接口即使返回 200,若异步写入没有成功,也未必算“好”。反过来,用户主动取消或明确的业务校验失败,是否计入分母也要先写清楚。

从用户旅程选择 SLI

SLI 采集与计算链路

不要为每个内部组件都设面向用户的 SLO。先列出登录、搜索、提交订单等用户动作,再为关键路径选少量指标。缓存命中率、队列积压等内部指标更适合作为定位原因的运行指标。

场景 推荐 SLI “好事件”定义示例
同步 API 可用性 + 延迟 非服务端错误,且 95% 请求在 300ms 内完成
异步任务 完成及时性 在承诺时限内完成且结果正确
流式消费 处理成功率 成功落库或被明确送入可追踪的死信队列

指标还要防止“分母漂移”。版本发布、采样策略或路由规则变化前后,分母口径必须保持一致;把探活、压测和内部批量流量混进去,会让用户体验被漂亮的数字掩盖。最实用的做法是把计算查询、标签过滤条件和例外分类放进代码仓库,并为它们做评审。

把百分比换算成可消费预算

例如,一个 30 天的时间可用性 SLO 为 99.9%,意味着最多允许约 43 分 12 秒不可用。若一个月有 200 万个有效请求,同样的目标则允许约 2,000 个坏请求。百分比抽象,预算却可以指导动作:当前已经花掉 70%,就应优先修复已知风险,而不是继续叠加高风险变更。

可以先把目标写成便于讨论的声明:

1
2
3
4
5
6
7
slo:
name: checkout-availability
window: 30d
target: 99.9%
valid_events: checkout requests excluding client cancellations
good_events: requests completed without server error
owner: payments-team

目标不必一开始就很高。没有基线时,先观察一段时间的真实表现,再与业务方确认用户可接受的失败与等待。把目标定成 100% 往往只会制造无效告警,并驱动团队为极少见的故障投入不成比例的成本。

用消耗速度设计告警

错误预算消耗与分级告警

只在“30 天成功率低于 99.9%”时报警太慢:预算可能早已在一小时内耗尽。更及时的指标是燃尽率(burn rate):

1
燃尽率 = 当前坏事件比例 / (1 - SLO 目标)

燃尽率为 1,表示正以刚好在整个窗口耗尽预算的速度失败。对 99.9% 目标,燃尽率 14.4 连续一小时大约会花掉月度预算的 2%,足以触发需要值班人员处理的快速告警。告警条件应同时查看短窗口和长窗口:短窗口发现突发,长窗口排除几分钟的偶发抖动。

1
2
3
4
5
6
7
alerts:
fast_burn:
when: burn_rate_5m > 14.4 and burn_rate_1h > 14.4
action: page-on-call
slow_burn:
when: burn_rate_30m > 3 and burn_rate_6h > 3
action: create-investigation-ticket

阈值不是照抄就能用。先用历史故障回放:一次真实的依赖超时、一次发布回滚、一次区域网络抖动,分别会怎样触发?值班人员收到告警后能否在十分钟内找到请求量、坏事件、版本和依赖的关联视图?不能回答的问题,要么补仪表盘,要么调整告警。

让预算进入发布决策

错误预算的价值不在于做一张红绿看板,而在于为风险取舍提供规则。预算充足时,可以安排灰度、重构和容量实验;预算接近耗尽时,暂停非必要发布,优先处理反复出现的失败模式。这里的“暂停”应有明确范围和退出条件,避免把一次局部问题升级成无限期冻结。

常见误区 更稳的做法
每个服务都设同一个 99.9% 按用户旅程、成本与历史基线分别设定
只看月度百分比 同时看预算余量与燃尽速度
4xx 全部忽略 明确区分业务拒绝、客户端取消与异常请求
告警后只看日志 从 SLI 看板跳转到版本、依赖和追踪上下文

落地清单

  • 选出一条高价值用户旅程,先定义一个可解释的 SLI。
  • 写清有效事件、好事件和例外请求的口径,并把查询纳入评审。
  • 用 30 天窗口和可接受的业务损失确定初始 SLO。
  • 将预算余量、燃尽率、请求量和版本信息放在同一排障视图。
  • 用短长双窗口设置快速与慢速告警,并用历史事故验证噪音。
  • 把预算状态纳入发布评审,定期复盘目标是否仍符合用户体验。

SLO 不会消灭故障,却能让告警、发布和修复都有一致依据。从一条关键路径开始,把口径和行动写清楚,可靠性才会成为可持续改进的工程能力。