2. Prometheus 误差预算计算:基于 Histogram 的 SLI 计算、基于 Counter 的 SLI 计算、误差预算率公式推导

误差预算(Error Budget)是 SRE 实践中的核心量化指标,它定义了服务在给定时间窗口内允许的最大不可用或低质量时间。要准确计算误差预算,首先需要从 Prometheus 指标中提取服务等级指标(SLI),然后根据 SLI 与 SLO 目标值推导出误差预算率。本章将系统讲解基于 Histogram 和 Counter 两种主流数据类型的 SLI 计算方法,并完成误差预算率的完整公式推导。

2.1 基于 Histogram 的 SLI 计算

Histogram(直方图)是 Prometheus 中最常用的 SLI 数据源,特别适用于延迟类指标(如请求耗时、响应时间)。Histogram 通过多个桶(bucket)记录观测值的分布,每个桶统计小于等于该桶上界值的样本数量。

2.1.1 Histogram 数据结构与 SLI 提取

典型的 HTTP 请求延迟 Histogram 指标如下:

# HELP http_request_duration_seconds request latency histogram
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.1"} 2400
http_request_duration_seconds_bucket{le="0.25"} 4500
http_request_duration_seconds_bucket{le="0.5"} 6200
http_request_duration_seconds_bucket{le="1.0"} 7100
http_request_duration_seconds_bucket{le="2.5"} 7350
http_request_duration_seconds_bucket{le="5.0"} 7400
http_request_duration_seconds_bucket{le="+Inf"} 7420
http_request_duration_seconds_count 7420
http_request_duration_seconds_sum 1283.5

要计算延迟类 SLI(例如:99% 的请求在 500ms 内完成),我们需要从 Histogram 中提取“良好请求”的数量。良好请求定义为延迟 ≤ SLO 阈值的请求。假设 SLO 阈值为 0.5 秒,则良好请求数即为 le="0.5" 桶的累积值。

关键公式: 良好请求数 = Histogram 中 le ≤ SLO 阈值的桶值

2.1.2 基于 Histogram 的 SLI 计算步骤

  1. 确定 SLO 阈值:例如延迟 SLO 为 “99% 的请求在 500ms 内完成”,则阈值为 0.5 秒。
  2. 提取良好请求数:使用 PromQL 查询 http_request_duration_seconds_bucket{le="0.5"}。
  3. 提取总请求数:使用 http_request_duration_seconds_count。
  4. 计算 SLI 比率:SLI = 良好请求数 / 总请求数。

对应的 PromQL 表达式:

# 延迟 SLI(良好请求占比)
(
  sum(rate(http_request_duration_seconds_bucket{le="0.5"}[5m]))
  /
  sum(rate(http_request_duration_seconds_count[5m]))
)

2.1.3 Histogram 计算的注意事项

注意事项 说明
桶边界选择 SLO 阈值必须与某个桶边界对齐,否则无法精确计算良好请求数。若阈值介于两个桶之间,需使用线性插值估算。
累积计数特性 Histogram 的桶是累积的,le="0.5" 包含所有 ≤0.5 秒的请求,无需额外累加。
速率 vs 原始值 计算 SLI 时通常使用 rate() 或 increase() 函数,避免因重启或时间窗口导致计数偏差。
多维度聚合 若服务有多个实例或端点,需使用 sum() 聚合所有相关维度。
最佳实践: 在定义 Histogram 桶时,建议将 SLO 阈值直接作为一个桶边界。例如,若 SLO 为 500ms,则桶应包含 le="0.5",避免插值误差。

2.2 基于 Counter 的 SLI 计算

Counter(计数器)适用于可用性、错误率等累加型指标。与 Histogram 不同,Counter 不提供分布信息,而是直接记录事件发生的次数。基于 Counter 的 SLI 计算通常用于“成功/失败”二元判定场景。

2.2.1 Counter 数据结构与 SLI 提取

典型的 HTTP 请求状态 Counter 指标如下:

# HELP http_requests_total total number of HTTP requests
# TYPE http_requests_total counter
http_requests_total{status="200"} 15000
http_requests_total{status="404"} 120
http_requests_total{status="500"} 35

要计算可用性 SLI(例如:99.9% 的请求成功),我们需要将状态码为 2xx/3xx 的请求视为成功,其余视为失败。

2.2.2 基于 Counter 的 SLI 计算步骤

  1. 定义成功条件:例如 HTTP 状态码为 2xx 或 3xx 视为成功。
  2. 提取成功请求数:使用 PromQL 过滤成功状态码并求和。
  3. 提取总请求数:所有状态码的请求总数。
  4. 计算 SLI 比率:SLI = 成功请求数 / 总请求数。

对应的 PromQL 表达式:

# 可用性 SLI(成功请求占比)
(
  sum(rate(http_requests_total{status=~"2[0-9][0-9]|3[0-9][0-9]"}[5m]))
  /
  sum(rate(http_requests_total[5m]))
)

2.2.3 Counter 与 Histogram 的对比

对比维度 Histogram Counter
适用场景 延迟、响应时间等分布型指标 可用性、错误率等累加型指标
数据粒度 提供分布信息(多桶) 仅提供总数
SLI 计算方式 良好请求数 = 桶值(le ≤ 阈值) 成功请求数 = 过滤条件求和
精度 受桶边界影响,可能需插值 精确计数,无分布误差
存储开销 较高(多桶 + 多标签) 较低(单指标 + 标签)

2.3 误差预算率公式推导

误差预算率(Error Budget Rate)是衡量 SLO 合规状态的核心指标,它表示在给定时间窗口内,服务已经消耗的误差预算比例。当误差预算率接近或超过 100% 时,意味着服务正在违反 SLO。

2.3.1 核心变量定义

变量 含义 单位
SLO_target 服务等级目标(例如 99.9%) 百分比
SLI 实际测量的服务等级指标 百分比
total_requests 时间窗口内的总请求数 计数
good_requests 时间窗口内的良好请求数 计数
bad_requests 时间窗口内的不良请求数(bad = total - good) 计数
error_budget_total 时间窗口内允许的最大不良请求数 计数
error_budget_consumed 时间窗口内已发生的不良请求数 计数
error_budget_rate 误差预算消耗率(已消耗 / 总预算) 百分比

2.3.2 公式推导过程

步骤 1:计算总误差预算

总误差预算 = 时间窗口内允许的不良请求数。根据 SLO 定义:

error_budget_total = total_requests × (1 - SLO_target)

例如,若 SLO_target = 99.9%,则允许的不良请求比例为 0.1%。

步骤 2:计算已消耗的误差预算

已消耗的误差预算 = 实际发生的不良请求数:

error_budget_consumed = bad_requests = total_requests - good_requests

步骤 3:计算误差预算率

误差预算率 = 已消耗预算 / 总预算:

error_budget_rate = error_budget_consumed / error_budget_total

代入变量:

error_budget_rate = (total_requests - good_requests) / (total_requests × (1 - SLO_target))

化简为:

error_budget_rate = (1 - SLI) / (1 - SLO_target)

其中 SLI = good_requests / total_requests。

最终公式: error_budget_rate = (1 - SLI) / (1 - SLO_target)

2.3.3 公式解读与示例

  • 当 SLI = SLO_target 时:error_budget_rate = 1,表示预算刚好用完。
  • 当 SLI > SLO_target 时:error_budget_rate < 1,表示预算有剩余。
  • 当 SLI < SLO_target 时:error_budget_rate > 1,表示预算超支,SLO 被违反。

示例计算:

假设 SLO_target = 99.9%,当前 SLI = 99.5%:

error_budget_rate = (1 - 0.995) / (1 - 0.999) = 0.005 / 0.001 = 5.0

这意味着误差预算消耗率达到了 500%,服务严重违反 SLO。

注意: 误差预算率是一个无量纲比率,通常以百分比或小数形式展示。在告警规则中,当 error_budget_rate > 1(即超过 100%)时,应触发告警。

2.4 误差预算计算流程总览

下图展示了从原始指标到误差预算率的完整计算流程:

误差预算计算流程总览 原始指标 SLO 目标值 数据类型判断 Histogram 处理 Counter 处理 SLI 计算 误差预算率计算 告警决策输入 关键公式 SLI = good / total error_budget_rate = (1 - SLI) / (1 - SLO)

2.5 误差预算率在 PromQL 中的实现

将上述公式转换为 PromQL 查询语句,即可实时计算误差预算率:

# 基于 Histogram 的误差预算率(延迟 SLO 示例)
(
  1 - (
    sum(rate(http_request_duration_seconds_bucket{le="0.5"}[5m]))
    /
    sum(rate(http_request_duration_seconds_count[5m]))
  )
)
/
(
  1 - 0.999  # SLO_target = 99.9%
)
# 基于 Counter 的误差预算率(可用性 SLO 示例)
(
  1 - (
    sum(rate(http_requests_total{status=~"2[0-9][0-9]|3[0-9][0-9]"}[5m]))
    /
    sum(rate(http_requests_total[5m]))
  )
)
/
(
  1 - 0.999  # SLO_target = 99.9%
)
生产建议: 将误差预算率计算封装为 Recording Rule,避免在告警规则中重复编写复杂 PromQL。例如:record: job:error_budget_rate:ratio_5m。

通过本章的学习,你已经掌握了基于 Histogram 和 Counter 的 SLI 计算方法,以及误差预算率的完整公式推导。这些知识是后续告警降噪策略和阈值联动设计的基础。