3. Error Budget 计算模型:基于 SLO 的预算计算公式、预算消耗速率、预算剩余周期与燃烧率(Burn Rate)概念
Error Budget(错误预算)是 SRE 实践中的核心量化工具,它将不可靠性视为一种可消耗的资源。本章将深入拆解 Error Budget 的计算模型,从基础公式推导到高级监控指标——燃烧率(Burn Rate),帮助你在自愈系统中实现精确的阈值动态调整。
3.1 基于 SLO 的预算计算公式
Error Budget 的定义非常直观:在 SLO 允许的范围内,系统可以“犯错”的总次数或总时间。其核心公式如下:
Error Budget = 1 - SLO(以小数表示)
或
Error Budget = 总请求量 × (1 - SLO)
在实际工程中,我们通常使用一个滚动窗口(例如 30 天)来计算。假设一个服务的月度 SLO 为 99.9%,月度总请求量为 10,000,000 次:
| 指标 | 数值 | 说明 |
|---|---|---|
| SLO | 99.9% | 服务等级目标 |
| 总请求量(30天) | 10,000,000 | 滚动窗口内的总事件数 |
| 允许的错误次数 | 10,000 | 10,000,000 × (1 - 0.999) |
| 初始 Error Budget | 10,000 次 | 周期开始时的可用预算 |
3.2 预算消耗速率与预算剩余周期
仅仅知道剩余预算是不够的,我们需要动态追踪其消耗速率,以预测预算何时会耗尽。这引出了两个关键衍生指标:
- 预算消耗速率(Budget Consumption Rate, BCR):单位时间内消耗的 Error Budget 比例。公式为:
BCR = (已消耗预算 / 总预算) / 时间窗口。 - 预算剩余周期(Time to Budget Exhaustion, TTE):在当前消耗速率下,预算预计还能维持的时间。公式为:
TTE = 剩余预算 / 当前消耗速率。
例如,一个 30 天周期的服务,在第 5 天结束时已经消耗了 50% 的预算:
消耗速率 = 50% / 5天 = 10% / 天
剩余预算 = 50%
TTE = 50% / 10% = 5 天
这意味着如果消耗速率保持不变,预算将在第 10 天耗尽,远早于 30 天的周期结束。这触发了自愈系统的预警。
3.3 燃烧率(Burn Rate)概念
燃烧率(Burn Rate)是 Error Budget 消耗速率的归一化表示,它衡量的是当前错误率相对于 SLO 允许错误率的倍数。这是自愈系统中触发熔断降级最敏感的指标。
Burn Rate = 实际错误率 / 允许错误率
其中:允许错误率 = 1 - SLO
假设 SLO 为 99.9%(允许错误率 0.1%),当前实际错误率为 1%:
Burn Rate = 1% / 0.1% = 10x
这意味着系统正在以 SLO 允许速率的 10 倍消耗预算。不同的 Burn Rate 对应不同的响应策略:
| Burn Rate 范围 | 消耗速率描述 | 推荐自愈动作 |
|---|---|---|
| 0 ~ 1x | 正常消耗,预算充足 | 无动作,持续监控 |
| 1x ~ 2x | 轻度超标,需关注 | 触发告警,人工评估 |
| 2x ~ 10x | 中度消耗,预算快速下降 | 启动局部熔断或限流 |
| 10x 以上 | 严重消耗,预算即将耗尽 | 全局熔断,降级至兜底服务 |
3.4 多窗口 Burn Rate 与自愈决策
为了平衡敏感性与稳定性,成熟的 Error Budget 驱动系统会同时监控多个时间窗口的 Burn Rate。下图展示了基于多窗口 Burn Rate 的自愈决策流程:
3.5 燃烧率与熔断阈值的映射关系
在自愈系统中,Burn Rate 直接决定了熔断降级的阈值。我们可以建立一个动态映射表,将 Burn Rate 映射到具体的熔断参数(如错误率阈值、拒绝请求比例):
// 伪代码示例:基于 Burn Rate 动态调整熔断阈值
function adjustCircuitBreakerThreshold(burnRate) {
if (burnRate > 10) {
// 紧急模式:拒绝 90% 请求,错误率阈值降至 1%
return { rejectionRate: 0.9, errorThreshold: 0.01 };
} else if (burnRate > 5) {
// 中度模式:拒绝 50% 请求,错误率阈值降至 5%
return { rejectionRate: 0.5, errorThreshold: 0.05 };
} else if (burnRate > 2) {
// 轻度模式:拒绝 20% 请求,错误率阈值降至 10%
return { rejectionRate: 0.2, errorThreshold: 0.1 };
} else {
// 正常模式:不主动拒绝,错误率阈值保持 SLO 水平
return { rejectionRate: 0.0, errorThreshold: 0.001 };
}
}