4. 慢查询诊断:使用 Prometheus 内置指标定位瓶颈
在告警自愈剧本中,PromQL 查询的响应速度直接决定了自愈动作的时效性。一个慢查询可能导致告警触发延迟、自愈剧本错过最佳执行窗口,甚至引发查询堆积拖垮 Prometheus 服务。Prometheus 自身暴露了 prometheus_engine_query_duration_seconds 指标,这是诊断慢查询的第一手数据源。
4.1 核心指标解读
prometheus_engine_query_duration_seconds 是一个 Summary 类型的指标,记录了 Prometheus 查询引擎执行查询的耗时分布。它按 slice(查询类型)和 stage(执行阶段)进行标签划分,帮助我们精准定位瓶颈环节。
| 标签 | 取值示例 | 说明 |
|---|---|---|
slice |
queries, rules, alerts, recording_rules |
查询来源:用户查询、规则评估、告警评估、记录规则 |
stage |
prepare, inner_eval, result_sort, merge |
执行阶段:准备、内部求值、结果排序、合并 |
诊断切入点: 在告警自愈场景中,重点关注
slice="alerts" 和 slice="rules" 的耗时数据,因为告警规则和记录规则的慢查询直接影响自愈剧本的触发与数据准备。
4.2 慢查询定位方法
通过以下 PromQL 查询,可以快速识别当前最慢的查询来源与阶段:
# 查询最近5分钟内,各查询来源的P99耗时
histogram_quantile(0.99,
sum(rate(prometheus_engine_query_duration_seconds_bucket{slice=~"queries|rules|alerts"}[5m])) by (le, slice)
)
# 查询各执行阶段的平均耗时
avg by (slice, stage) (
rate(prometheus_engine_query_duration_seconds_sum[5m])
/
rate(prometheus_engine_query_duration_seconds_count[5m])
)
# 识别耗时超过阈值的告警规则评估
prometheus_engine_query_duration_seconds{slice="alerts", quantile="0.99"} > 1.0
注意: 使用
histogram_quantile 时,必须确保 le 标签完整且桶边界覆盖实际耗时范围。如果桶上界不足,P99 计算会失真。
4.3 瓶颈阶段分析
不同的 stage 值对应不同的瓶颈类型,下表总结了常见问题与优化方向:
| 阶段 | 典型耗时原因 | 优化建议 |
|---|---|---|
prepare |
查询解析、标签匹配器构建、时间范围裁剪 | 简化 PromQL 表达式,避免嵌套过深的聚合函数 |
inner_eval |
数据扫描、向量匹配、范围向量计算 | 减少查询时间范围,使用 offset 替代大范围回溯 |
result_sort |
结果排序、TopK 计算 | 避免在大量时间序列上使用 sort 或 topk |
merge |
多分片结果合并(仅限 Thanos/Cortex 场景) | 检查分片策略,减少跨分片查询 |
4.4 告警自愈场景实战案例
某生产环境中,告警自愈剧本频繁出现“规则评估超时”错误。通过慢查询诊断,发现 slice="alerts" 的 inner_eval 阶段 P99 耗时高达 8.2 秒。
诊断步骤:
- 执行
avg by (stage) (rate(prometheus_engine_query_duration_seconds_sum{slice="alerts"}[5m]) / rate(prometheus_engine_query_duration_seconds_count{slice="alerts"}[5m])),确认inner_eval耗时占比超过 85%。 - 检查告警规则中的 PromQL,发现一条规则使用了
rate(metric[24h])大范围回溯,且未使用offset优化。 - 将时间范围缩小至
[1h],并增加offset 10m避免数据延迟影响。 - 优化后,
inner_eval阶段 P99 耗时降至 0.3 秒,告警自愈剧本恢复正常。
4.5 建立慢查询告警
将慢查询诊断自动化,当 Prometheus 自身查询耗时超过阈值时,触发告警通知 SRE 介入:
# 告警规则:Prometheus 查询 P99 耗时超过 2 秒
- alert: PrometheusSlowQuery
expr: |
histogram_quantile(0.99,
sum(rate(prometheus_engine_query_duration_seconds_bucket{slice=~"queries|rules|alerts"}[5m])) by (le, slice)
) > 2
for: 5m
labels:
severity: warning
annotations:
summary: "Prometheus 查询 P99 耗时超过 2 秒 (slice: {{ $labels.slice }})"
description: "当前 P99 耗时 {{ $value | humanizeDuration }},请检查相关 PromQL 是否需要优化。"
最佳实践: 将慢查询告警与自愈剧本联动。当检测到
slice="alerts" 的 P99 耗时持续升高时,自动触发“临时降低告警规则评估频率”或“启用查询缓存”的自愈动作,避免告警系统自身成为瓶颈。