4. SLI 指标采集:请求成功率、延迟分布、错误率指标的 PromQL 查询

SLI(Service Level Indicator)是 SLO 体系的量化基石。在 Grafana 看板中,SLI 的采集质量直接决定告警准确性与自愈触发时机。本章聚焦三大核心 SLI 的 PromQL 查询模式:请求成功率、延迟分布与错误率,并给出可直接嵌入看板面板的查询模板。

4.1 三大 SLI 的 PromQL 查询模板

以下表格汇总了三种 SLI 的典型 PromQL 表达式、适用场景与常见数据源标签约定。所有查询均基于 prometheus_http_requests_total 与 prometheus_http_request_duration_seconds_bucket 示例指标,实际使用时替换为业务指标名即可。

SLI 类型 PromQL 查询 说明 常用标签
请求成功率
sum(rate(prometheus_http_requests_total{status=~"2..|3.."}[5m]))
/
sum(rate(prometheus_http_requests_total[5m]))
5 分钟内 2xx/3xx 请求占比,范围 0~1 status, method, handler
延迟分布 (p99)
histogram_quantile(0.99,
  sum(rate(prometheus_http_request_duration_seconds_bucket[5m])) by (le))
基于直方图计算 p99 延迟,单位秒 le, handler
错误率
sum(rate(prometheus_http_requests_total{status=~"5.."}[5m]))
/
sum(rate(prometheus_http_requests_total[5m]))
5 分钟内 5xx 错误占比,通常要求 < 0.001 status, method
实践提示: 成功率与错误率之和不一定等于 1,因为 4xx 请求既不算成功也不算服务端错误。建议将 4xx 单独归类为“客户端错误”,不计入 SLO 燃烧率计算。

4.2 延迟分布的多分位采集策略

仅采集 p99 不足以全面评估延迟健康度。推荐同时采集 p50、p90、p99 三个分位,形成延迟分布视图。以下为多分位查询模板:

# p50 延迟
histogram_quantile(0.50, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))

# p90 延迟
histogram_quantile(0.90, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))

# p99 延迟
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))

在 Grafana 面板中,可将三条查询合并为同一张时间序列图,使用不同颜色区分分位线,便于快速识别延迟拐点。

避坑提醒: 直方图 bucket 配置必须覆盖业务延迟范围。若最大 bucket 仅为 1s,则 p99 会被截断在 1s 以内,无法反映真实长尾延迟。建议将最大 bucket 设置为 SLO 延迟阈值的 5~10 倍。

4.3 SLI 采集架构与数据流

下图展示了从业务服务到 Grafana 看板的 SLI 数据采集链路,包含指标暴露、Prometheus 抓取、Recording Rule 预计算与看板查询四个关键环节。

SLI 采集架构与数据流 业务服务 /metrics 端点 Prometheus scrape_interval: 15s Recording Rules 预聚合 SLI Grafana 看板查询 指标示例 # HELP prometheus_http_requests_total HTTP 请求总数 # TYPE prometheus_http_requests_total counter prometheus_http_requests_total{status="200",method="GET",handler="/api/v1/query"} 1024 Recording Rule 示例 (rules/sli.rules.yml) record: sli:request_success_rate:5m expr: sum(rate(prometheus_http_requests_total{status=~"2..|3.."}[5m])) / sum(rate(prometheus_http_requests_total[5m]))
Recording Rule 最佳实践: 将频繁查询的 SLI 表达式定义为 Recording Rule,可降低 Prometheus 查询压力,并让 Grafana 面板响应更快。建议为每个 SLI 创建独立的 rule 文件,按 sli:<指标名>:<时间窗口> 格式命名。

4.4 错误率与成功率的互斥关系

在实际看板设计中,错误率与成功率并非简单的 1:1 互补。以下表格澄清了常见状态码分类与 SLI 归属:

状态码范围 分类 是否计入成功率 是否计入错误率 SLI 处理建议
2xx 成功 是 否 计入分子分母
3xx 重定向 是 否 计入分子分母
4xx 客户端错误 否 否 单独监控,不计入 SLO
5xx 服务端错误 否 是 计入错误率分子
常见误区: 不要将 4xx 错误计入错误率 SLI。4xx 通常由客户端输入错误引起,不应触发服务端 SLO 告警。若业务需要跟踪 4xx 趋势,应单独建立“客户端错误率”面板,与 SLO 告警解耦。

4.5 多维度 SLI 聚合查询

当需要按 服务、端点 或 地域 维度拆分 SLI 时,需在 PromQL 中保留对应标签。以下为按 handler 维度聚合的成功率查询:

# 按 handler 维度聚合成功率
sum by (handler) (
  rate(prometheus_http_requests_total{status=~"2..|3.."}[5m])
)
/
sum by (handler) (
  rate(prometheus_http_requests_total[5m])
)

在 Grafana 中,可将 handler 设为图例模板变量 {{handler}},实现多线对比。若维度过多(如超过 20 个),建议使用 Top 10 排序或 降采样 避免面板过载。

4.6 SLI 采集的常见陷阱与校验方法

  • 指标缺失: 新部署的服务未暴露 /metrics 端点,导致 Prometheus 抓取失败。校验方法:在 Prometheus Target 页面检查 up 指标是否为 1。
  • 标签爆炸: 高基数标签(如 user_id、request_id)导致 Prometheus 内存飙升。校验方法:使用 count by (handler) (metric) 检查标签基数。
  • 时间窗口不一致: 成功率使用 5m 窗口,错误率使用 1m 窗口,导致燃烧率计算偏差。校验方法:统一所有 SLI 的时间窗口为相同值。
  • 直方图 bucket 泄漏: 延迟分布出现 +Inf 占比过高,说明最大 bucket 设置过小。校验方法:检查 le="+Inf" 的计数是否显著高于前一个 bucket。
快速校验命令: 在 Prometheus 自带的 Graph 页面中,直接输入 SLI 查询并切换为 Table 视图,可查看最近一次的数值。若返回 NaN 或 Inf,说明分母为零或指标名错误。

通过以上 PromQL 模板与采集策略,你可以在 Grafana 看板中稳定获取请求成功率、延迟分布与错误率三大 SLI,为后续 SLO 燃烧率计算与自愈剧本触发提供可靠的数据基础。