3. Error Budget 的数学计算:基于时间窗口的实时度量

Error Budget 的数学计算是告警阈值调优的量化基础。只有精确掌握 总量、消耗速率 和 剩余 Budget,SRE 团队才能判断当前系统的可靠性是否“超支”,并决定是否触发自动化熔断或降级策略。本节将围绕 30 天滑动时间窗口,给出完整的计算公式与实时计算方法。

3.1 核心概念与时间窗口定义

Error Budget 的计算基于一个固定的 滑动时间窗口(通常为 30 天)。窗口长度决定了 Budget 的“刷新周期”和“历史记忆长度”。

概念 符号 定义
SLO 目标 SLO_target 服务在时间窗口内应达到的可用性百分比(如 99.9%)
总请求量 R_total 时间窗口内所有合法请求的总数
允许错误量 E_allowed 在 SLO 目标下,窗口内允许的最大错误请求数
实际错误量 E_actual 窗口内实际发生的错误请求数
Error Budget 总量 EB_total 窗口起始时分配的“可犯错配额”
剩余 Error Budget EB_remaining 当前时刻尚未消耗的配额
关键公式: Error Budget 总量 = 总请求量 × (1 - SLO_target)。例如:30 天内总请求 10,000,000 次,SLO = 99.9%,则 EB_total = 10,000,000 × 0.001 = 10,000 次错误。

3.2 基于 30 天滑动窗口的 Error Budget 总量计算

在真实生产环境中,Error Budget 总量并非静态值,而是随着滑动窗口内总请求量的变化而动态更新。计算分为两个步骤:

  1. 统计窗口总请求量:聚合过去 30 天(精确到秒)的所有合法请求计数。
  2. 计算允许错误量:EB_total = R_total × (1 - SLO_target)。

以下是一个基于 Prometheus 查询语言的实时计算示例:

# 计算 30 天滑动窗口内的总请求量(假设指标名为 http_requests_total)
sum(
  rate(http_requests_total[30d])
) * 30 * 24 * 3600

# 计算 30 天滑动窗口内的 Error Budget 总量(SLO = 99.9%)
sum(
  rate(http_requests_total[30d])
) * 30 * 24 * 3600 * 0.001
实践建议: 使用 rate() 函数时,注意时间范围必须与窗口长度一致。如果使用 increase(),需确保数据点覆盖完整窗口,避免因数据缺失导致总量计算偏差。

3.3 消耗速率与剩余 Budget 的实时计算方法

消耗速率决定了 Error Budget 的“燃烧速度”,是触发告警和自动化策略的核心指标。剩余 Budget 则直接反映当前系统的“健康余量”。

3.3.1 消耗速率计算

消耗速率定义为 单位时间内实际错误量的滑动平均值。通常使用 1 小时、6 小时或 24 小时的窗口来计算瞬时速率。

# 实时错误速率(每秒错误数)
rate(http_errors_total[5m])

# 消耗速率占允许速率的百分比(燃烧率)
rate(http_errors_total[5m]) / (EB_total / (30 * 24 * 3600))

3.3.2 剩余 Budget 实时计算

剩余 Budget 的计算公式为:

EB_remaining = EB_total - E_actual_window

其中 E_actual_window 是过去 30 天滑动窗口内的实际错误总数。

# 实时剩余 Error Budget(值)
EB_total - sum(increase(http_errors_total[30d]))

# 实时剩余 Error Budget(百分比)
(EB_total - sum(increase(http_errors_total[30d]))) / EB_total * 100
常见陷阱: 当使用 increase() 函数计算 30 天窗口时,如果服务在窗口早期发生过重启或指标重置,会导致错误计数被低估。建议使用 rate() 乘以窗口时长来避免计数器重置问题。

3.4 Error Budget 实时计算流程(SVG 架构图)

下图展示了从原始指标采集到剩余 Budget 输出的完整实时计算链路:

Error Budget 实时计算流程 指标采集层 请求数 / 错误数 30天滑动窗口聚合 rate() / increase() EB 总量计算 R_total × (1 - SLO) 实际错误量 E_actual (30d) 消耗速率计算 rate(errors[5m]) 剩余 Budget EB_total - E_actual 告警引擎 / 自动化触发 燃烧率 > 阈值 → 告警 说明:虚线表示可选数据流;实际部署中,消耗速率和剩余 Budget 可独立触发告警,也可组合使用。

3.5 实时计算示例:30 天窗口下的 Budget 演化

假设某服务 SLO = 99.9%,30 天总请求量稳定在 10,000,000 次。下表展示了不同时间点的 Budget 状态:

时间点 总请求量 (30d) EB 总量 实际错误量 (30d) 剩余 Budget 剩余百分比 状态
T0(窗口起始) 10,000,000 10,000 0 10,000 100% 健康
T1(第 10 天) 10,000,000 10,000 3,000 7,000 70% 正常
T2(第 20 天) 10,000,000 10,000 8,500 1,500 15% ⚠️ 告警阈值
T3(第 25 天) 10,000,000 10,000 10,000 0 0% 🚨 Budget 耗尽
关键洞察: 当剩余 Budget 低于 20% 时,应触发 多窗口燃烧率告警(如 1 小时窗口燃烧率 > 10 倍允许速率),而非仅依赖剩余百分比。因为剩余百分比是滞后指标,而燃烧率是领先指标。

3.6 多时间窗口的 Budget 消耗速率对比(SVG 图)

下图对比了不同时间窗口下消耗速率的变化趋势,帮助理解为何需要多窗口联合告警:

不同时间窗口的消耗速率对比 1h 窗口(高灵敏度) 6h 窗口(中等) 24h 窗口(低灵敏度) 高 中 低 消耗速率 0h 12h 24h 36h 告警阈值 短窗口(1h)对突发错误敏感,长窗口(24h)平滑噪声;多窗口联合告警可同时捕获突发和持续消耗。

3.7 实时计算的工程实现要点

  • 数据源选择:优先使用分布式追踪或请求日志中的精确错误计数,避免依赖采样数据。
  • 窗口对齐:确保所有计算使用相同的滑动窗口边界(如精确到秒的 30 天),避免因时间偏移导致 Budget 计算不一致。
  • 缓存与预计算:对于高 QPS 服务,建议每 1 分钟预计算一次 EB_total 和 EB_remaining,避免每次告警评估都全量扫描 30 天数据。
  • 指标命名规范:在 Prometheus 或类似系统中,建议使用 error_budget_total、error_budget_remaining、error_budget_burn_rate 作为标准指标名,便于团队统一理解。
自动化触发策略的数学基础: 当 EB_remaining < 20% 且 burn_rate_1h > 10 时,触发“严重告警”并自动执行流量切换或降级。这个组合条件同时考虑了 存量(剩余 Budget) 和 增量(消耗速率),是业界最佳实践。