多窗口燃烧速率算法:1小时、6小时、24小时、72小时窗口的燃烧速率计算逻辑与代码实现
在SRE实践中,单一时间窗口的燃烧速率往往无法全面反映服务可靠性的真实状态。短窗口(如1小时)对突发故障敏感,但容易产生误报;长窗口(如72小时)能平滑噪声,但响应延迟较高。多窗口燃烧速率算法通过组合多个时间窗口的燃烧速率,实现告警的快速检测与噪声抑制。
1. 燃烧速率核心定义
燃烧速率(Burn Rate)衡量的是错误预算消耗的速度。其计算公式为:
Burn Rate = (窗口内错误率) / (SLO目标错误率)
其中:
- 窗口内错误率 = 窗口内错误请求数 / 窗口内总请求数
- SLO目标错误率 = 1 - SLO目标值(例如99.9% SLO对应0.001)
当 Burn Rate > 1 时,表示错误预算正在以高于预期的速度消耗;当 Burn Rate > 14.4(即1小时消耗完30天预算)时,通常触发紧急告警。
2. 多窗口燃烧速率计算逻辑
本课程采用四个标准时间窗口:1小时、6小时、24小时、72小时。每个窗口独立计算燃烧速率,并通过阈值联动实现告警降噪。
| 窗口名称 | 窗口时长 | 敏感度 | 典型用途 | 告警阈值(示例) |
|---|---|---|---|---|
| 短窗口 | 1小时 | 高 | 快速检测突发故障 | ≥ 14.4 |
| 中短窗口 | 6小时 | 中高 | 检测持续异常 | ≥ 6.0 |
| 中长窗口 | 24小时 | 中低 | 检测慢速退化 | ≥ 3.0 |
| 长窗口 | 72小时 | 低 | 趋势分析与噪声过滤 | ≥ 1.5 |
阈值联动原则:短窗口阈值高(容忍突发),长窗口阈值低(敏感于持续退化)。告警触发条件通常为“任意窗口超过阈值”或“多窗口同时超过阈值”,后者可显著降低误报率。
3. 多窗口燃烧速率算法流程图
下图展示了四个窗口的并行计算流程与阈值判定逻辑:
4. 代码实现:多窗口燃烧速率计算
以下Go语言代码实现了四个时间窗口的燃烧速率并行计算与阈值判定:
package main
import (
"fmt"
"sync"
"time"
)
// WindowConfig 定义时间窗口配置
type WindowConfig struct {
Name string
Duration time.Duration
Threshold float64
}
// BurnRateResult 存储单个窗口的计算结果
type BurnRateResult struct {
WindowName string
BurnRate float64
Exceeded bool
}
// CalculateBurnRate 计算单个窗口的燃烧速率
func CalculateBurnRate(errors, total int64, sloTarget float64) float64 {
if total == 0 {
return 0
}
errorRate := float64(errors) / float64(total)
targetErrorRate := 1 - sloTarget
if targetErrorRate == 0 {
return 0
}
return errorRate / targetErrorRate
}
// MultiWindowBurnRate 并行计算多窗口燃烧速率
func MultiWindowBurnRate(errors, total int64, sloTarget float64, windows []WindowConfig) []BurnRateResult {
var wg sync.WaitGroup
results := make([]BurnRateResult, len(windows))
for i, w := range windows {
wg.Add(1)
go func(idx int, config WindowConfig) {
defer wg.Done()
burnRate := CalculateBurnRate(errors, total, sloTarget)
results[idx] = BurnRateResult{
WindowName: config.Name,
BurnRate: burnRate,
Exceeded: burnRate >= config.Threshold,
}
}(i, w)
}
wg.Wait()
return results
}
// EvaluateAlert 评估是否触发告警(多窗口联动)
func EvaluateAlert(results []BurnRateResult, requireMultiple bool, minWindows int) bool {
exceededCount := 0
for _, r := range results {
if r.Exceeded {
exceededCount++
if !requireMultiple {
return true // 任意窗口超阈值即告警
}
}
}
return requireMultiple && exceededCount >= minWindows
}
func main() {
// 定义四个时间窗口
windows := []WindowConfig{
{Name: "1小时", Duration: 1 * time.Hour, Threshold: 14.4},
{Name: "6小时", Duration: 6 * time.Hour, Threshold: 6.0},
{Name: "24小时", Duration: 24 * time.Hour, Threshold: 3.0},
{Name: "72小时", Duration: 72 * time.Hour, Threshold: 1.5},
}
// 模拟数据:99.9% SLO,窗口内错误请求50,总请求10000
sloTarget := 0.999
errors := int64(50)
total := int64(10000)
// 并行计算
results := MultiWindowBurnRate(errors, total, sloTarget, windows)
// 输出结果
fmt.Println("多窗口燃烧速率计算结果:")
fmt.Println("================================")
for _, r := range results {
status := "✅ 正常"
if r.Exceeded {
status = "⚠️ 超阈值"
}
fmt.Printf("%-8s | Burn Rate: %8.4f | %s\n", r.WindowName, r.BurnRate, status)
}
// 联动判定:至少2个窗口超阈值才告警
alert := EvaluateAlert(results, true, 2)
fmt.Println("================================")
if alert {
fmt.Println("🔔 触发告警:多窗口燃烧速率超标")
} else {
fmt.Println("✅ 未触发告警:燃烧速率在可接受范围")
}
}
5. 多窗口联动策略对比
不同的联动策略适用于不同的场景,下表对比了三种常见策略:
| 联动策略 | 判定条件 | 误报率 | 漏报率 | 适用场景 |
|---|---|---|---|---|
| OR策略 | 任意窗口超阈值即告警 | 高 | 低 | 关键业务、容忍度低 |
| AND策略 | 所有窗口同时超阈值才告警 | 低 | 高 | 非关键业务、噪声大 |
| N-of-M策略 | 至少N个窗口超阈值(推荐) | 中 | 中 | 通用场景、平衡敏感度 |
生产实践建议:推荐使用 N-of-M策略,通常设置为“4个窗口中至少2个超阈值”。这种配置既能快速响应突发故障(1小时窗口会迅速超阈值),又能过滤掉短时抖动(仅1个窗口超阈值时不告警)。
6. 多窗口燃烧速率联动判定流程图
下图展示了N-of-M联动策略的详细判定逻辑:
常见陷阱:不要对所有窗口使用相同的阈值。短窗口阈值过低会导致频繁误报,长窗口阈值过高会导致漏报。阈值设置应基于SLO目标和错误预算消耗速度进行数学推导,而非经验猜测。
7. 阈值推导公式
每个窗口的阈值可以通过以下公式推导:
阈值 = (窗口时长 / 错误预算耗尽时间) × (1 - SLO目标) / (1 - SLO目标)
简化后:
阈值 = 窗口时长 / 错误预算耗尽时间
例如:30天预算在1小时内耗尽
阈值 = 1小时 / (30天 × 24小时) = 1 / 720 ≈ 0.00139
但这是错误率比值,转换为燃烧速率:
Burn Rate = 0.00139 / (1 - 0.999) = 1.39
实际上,1小时消耗完30天预算的燃烧速率为:
(30 × 24) / 1 = 720倍
即 Burn Rate = 720 时,1小时耗尽全部预算。
常用阈值(99.9% SLO):
- 1小时耗尽预算:Burn Rate = 720
- 5%预算在1小时内耗尽:Burn Rate = 720 × 5% = 36
- 2%预算在1小时内耗尽:Burn Rate = 720 × 2% = 14.4(常用)
阈值速查表(99.9% SLO):
- 1小时窗口:14.4(对应2%预算消耗)
- 6小时窗口:6.0(对应5%预算消耗)
- 24小时窗口:3.0(对应10%预算消耗)
- 72小时窗口:1.5(对应15%预算消耗)
- 1小时窗口:14.4(对应2%预算消耗)
- 6小时窗口:6.0(对应5%预算消耗)
- 24小时窗口:3.0(对应10%预算消耗)
- 72小时窗口:1.5(对应15%预算消耗)