4. PromQL 编写 SLI:使用 histogram_quantile 计算延迟分位数,rate 计算错误率

SLI(Service Level Indicator)是 SLO 的量化基石。在 Prometheus 生态中,延迟和错误是最核心的两个黄金信号。本章将聚焦如何用 PromQL 精确编写这两类 SLI,并确保查询在性能与语义上均符合生产标准。

4.1 延迟分位数 SLI:histogram_quantile

延迟通常以 Histogram 类型采集,PromQL 通过 histogram_quantile(φ, scalar, instant-vector) 计算指定分位数的近似值。典型场景:99% 的请求在 200ms 内完成。

4.1.1 标准查询模板

# 计算过去 5 分钟所有请求的 p99 延迟(秒)
histogram_quantile(0.99,
  sum by (le) (
    rate(http_request_duration_seconds_bucket[5m])
  )
)
关键点:
  • rate(...[5m]) 将累积计数器转换为每秒速率,消除重启与时间窗口影响。
  • sum by (le) 按桶边界聚合,确保多实例数据正确合并。
  • 分位数 φ 必须介于 0 ~ 1 之间,常用 0.5、0.9、0.99、0.999。

4.1.2 多维度分位数(按服务/端点拆分)

# 按 service 和 endpoint 维度计算 p99 延迟
histogram_quantile(0.99,
  sum by (le, service, endpoint) (
    rate(http_request_duration_seconds_bucket[5m])
  )
)
维度 说明 典型值
service 微服务名称 api-gateway, user-svc
endpoint API 路径或 RPC 方法 /v1/orders, GetUser
le Histogram 桶上界(必须保留) 0.1, 0.5, 1.0, +Inf
⚠ 性能陷阱: 避免在 histogram_quantile 内使用 avg 或 max 聚合桶数据,这会导致分位数计算失真。始终使用 sum by (le, ...) 保持桶结构完整。

4.2 错误率 SLI:rate

错误率定义为 错误请求数 / 总请求数。Prometheus 通常使用两个 Counter 指标:http_requests_total(总请求)和 http_requests_total{status=~"5.."}(错误请求)。

4.2.1 标准错误率查询

# 过去 5 分钟的错误率(百分比)
(
  sum by (service) (
    rate(http_requests_total{status=~"5[0-9][0-9]"}[5m])
  )
  /
  sum by (service) (
    rate(http_requests_total[5m])
  )
) * 100
💡 最佳实践: 使用 status=~"5.." 正则匹配 5xx 状态码,而非硬编码每个错误码。对于 gRPC,使用 grpc_code=~"^[2-9].." 匹配非 OK 状态。

4.2.2 排除健康检查与低流量时段

# 排除 /health 端点,避免稀释错误率
(
  sum by (service) (
    rate(http_requests_total{status=~"5[0-9][0-9]", endpoint!="/health"}[5m])
  )
  /
  sum by (service) (
    rate(http_requests_total{endpoint!="/health"}[5m])
  )
) * 100

4.3 延迟与错误率 SLI 的 PromQL 结构对比

SLI 类型 核心函数 聚合方式 典型时间窗口 输出单位
延迟分位数 histogram_quantile sum by (le, ...) 5m / 10m 秒(s)
错误率 rate sum by (...) 5m / 1m 百分比(%)

4.4 延迟分位数计算流程(SVG)

延迟分位数 SLI 计算流程 原始 Histogram 桶 rate(…[5m]) sum by (le) histogram_quantile(0.99, …) p99 延迟值 📌 说明: rate 将累积桶转为每秒速率 → sum by (le) 合并多实例桶 → histogram_quantile 插值计算分位数。

4.5 错误率计算流程(SVG)

错误率 SLI 计算流程 总请求 rate 错误请求 rate 除法 / × 100 📌 说明:两个 rate 使用相同时间窗口(如 5m),确保分子分母时间对齐,避免计算偏差。

4.6 常见错误与调优建议

  • 桶数量不足: 如果 Histogram 桶少于 10 个,histogram_quantile 插值误差会显著增大。建议至少配置 15~20 个桶,覆盖预期延迟范围。
  • 时间窗口过短: rate(...[1m]) 在低流量服务中容易抖动,推荐使用 [5m] 或 [10m] 作为 SLI 窗口。
  • 未排除零值桶: 如果 +Inf 桶速率异常高,说明桶上界设置过小,应扩展最大桶值。
  • 错误率分母为 0: 当窗口内无请求时,除法返回 NaN。建议使用 or vector(0) 兜底:(... / ...) or vector(0)。
✅ 生产级 SLI 查询示例(完整版):
# p99 延迟 SLI
histogram_quantile(0.99,
  sum by (le, service) (
    rate(http_request_duration_seconds_bucket[5m])
  )
)

# 错误率 SLI(含 NaN 保护)
(
  sum by (service) (
    rate(http_requests_total{status=~"5[0-9][0-9]"}[5m])
  )
  /
  sum by (service) (
    rate(http_requests_total[5m])
  )
  or vector(0)
) * 100