3. PromQL 入门:常用查询语法、聚合操作与时间范围选择
PromQL(Prometheus Query Language)是 Prometheus 生态中最核心的查询语言,也是实现指标驱动降级熔断策略的“翻译器”。在 SRE 场景中,我们通过 PromQL 将原始指标转化为可决策的阈值、速率、比例和趋势信号。本章从最常用的查询语法出发,逐步深入到聚合操作与时间范围选择,确保你能在作业模板中准确表达熔断条件。
3.1 即时查询与范围查询
PromQL 的查询结果分为两种类型:即时向量(Instant Vector) 和 范围向量(Range Vector)strong>。理解两者的区别是正确使用时间范围选择的前提。
| 查询类型 | 语法示例 | 返回结果 | 典型用途 |
|---|---|---|---|
| 即时查询 | http_requests_total{status="500"} |
每个时间序列在当前时刻的一个样本值 | 实时告警、当前状态判断 |
| 范围查询 | http_requests_total{status="500"}[5m] |
每个时间序列在过去 5 分钟内的一组样本值 | 计算速率、趋势、分位数 |
SRE 实战提示:在降级熔断作业模板中,范围查询是主力。例如判断“过去 1 分钟内错误率是否超过 5%”,必须使用
[1m] 或 [5m] 范围选择器来获取足够的数据窗口,避免单点抖动导致误熔断。
3.2 常用选择器与标签过滤
PromQL 通过标签选择器(Label Selector)精确匹配目标指标。掌握以下四种匹配模式,可以让你在复杂微服务架构中快速定位目标服务。
- 精确匹配(=):
http_requests_total{job="api-gateway"}—— 只匹配 job 标签完全等于api-gateway的序列。 - 正则匹配(=~):
http_requests_total{job=~"api-.*"}—— 匹配 job 标签以api-开头的所有序列。 - 反向匹配(!=):
http_requests_total{job!="health-check"}—— 排除 job 为health-check的序列。 - 反向正则(!~):
http_requests_total{job!~".*-canary"}—— 排除 job 以-canary结尾的序列。
避坑指南:正则匹配在标签基数较高时可能带来性能开销。在熔断作业模板中,尽量使用精确匹配或有限的正则范围,避免使用
.* 全量匹配。
3.3 聚合操作:从多维度到单信号
降级熔断决策通常需要将多个实例、多个 Pod 的指标聚合成一个全局信号。PromQL 提供 sum()、avg()、max()、min()、count() 等聚合函数,配合 by 和 without 子句控制维度保留。
# 聚合所有实例的 5xx 请求总数(按 job 维度保留)
sum by (job) (http_requests_total{status=~"5.."})
# 计算所有实例的平均请求延迟(去掉 instance 标签)
avg without (instance) (http_request_duration_seconds_sum / http_request_duration_seconds_count)
# 取所有实例中的最大错误率(用于熔断判断)
max by (service) (
rate(http_requests_total{status="500"}[5m])
/
rate(http_requests_total[5m])
)
注意:聚合操作会改变时间序列的标签结构。在作业模板中,
by 子句保留的标签必须与后续告警规则或熔断条件中的标签一致,否则会导致查询结果为空。
3.4 时间范围选择与速率计算
原始计数器(如 http_requests_total)是单调递增的,直接使用无法反映当前负载。必须通过 rate() 或 irate() 函数将其转换为每秒速率。时间范围选择器 [5m] 决定了速率计算的平滑窗口。
| 函数 | 计算方式 | 适用场景 |
|---|---|---|
rate()[5m] |
窗口内总增量 / 窗口时长 | 平滑趋势,适合告警与熔断 |
irate()[5m] |
最后两个样本的增量 / 时间差 | 敏感峰值检测,适合短时突发 |
increase()[5m] |
窗口内总增量(值) | 计算窗口内总量,如 5 分钟错误数 |
# 推荐:使用 rate() 计算 5 分钟平均错误率
rate(http_requests_total{status="500"}[5m])
# 敏感场景:使用 irate() 捕捉瞬时错误飙升
irate(http_requests_total{status="500"}[5m])
# 总量场景:过去 5 分钟错误请求总数
increase(http_requests_total{status="500"}[5m])
最佳实践:在降级熔断作业模板中,优先使用
rate()[5m]。它既能过滤掉采集抖动,又能保持对持续恶化的敏感性。如果业务要求秒级响应(如高频交易),可改用 irate()[1m],但需配合更严格的抖动容忍策略。
3.5 常用 PromQL 模式:降级熔断场景实战
以下 PromQL 模式直接对应降级熔断作业模板中的典型判断逻辑,建议作为标准片段复用。
| 场景 | PromQL 表达式 | 说明 |
|---|---|---|
| 错误率超过阈值 | sum(rate(http_requests_total{status="500"}[5m])) / sum(rate(http_requests_total[5m])) > 0.05 |
5 分钟错误率 > 5% |
| 平均延迟飙升 | histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) > 2.0 |
P95 延迟 > 2 秒 |
| 请求量骤降 | rate(http_requests_total[5m]) / rate(http_requests_total[30m]) < 0.3 |
当前流量低于过去 30 分钟均值的 30% |
| 实例健康度 | count by (job) (up == 0) > 2 |
同一 job 下超过 2 个实例宕机 |
模板化建议:将上述 PromQL 表达式封装为作业模板中的 熔断条件变量。例如
${circuit_breaker_error_rate} 对应错误率表达式,${circuit_breaker_latency_p95} 对应延迟表达式。这样在调整阈值时只需修改变量,无需重写整个查询。
3.6 时间范围选择的最佳实践
时间范围选择器 [d] 中的 d 值直接影响熔断的灵敏度和稳定性。选择过短会导致频繁误触发,选择过长则可能错过快速恢复窗口。
- 1m ~ 2m:适用于高频交易、实时风控等对延迟极度敏感的场景。配合
irate()使用,但必须增加抖动容忍逻辑(如连续 3 次采样均超阈值才触发)。 - 5m:推荐默认值。适用于大多数微服务降级熔断场景,既能平滑瞬时波动,又能在 2~3 个采集周期内响应持续恶化。
- 10m ~ 30m:适用于慢速退化场景(如内存泄漏、连接池耗尽)。配合
avg_over_time()或min_over_time()使用,避免短期抖动干扰。
# 5 分钟窗口 + 连续 3 次超阈值才触发(通过 recording rule 实现)
# 第一步:计算 5 分钟错误率
- record: job:error_rate:5m
expr: sum(rate(http_requests_total{status="500"}[5m])) / sum(rate(http_requests_total[5m]))
# 第二步:判断连续 3 次均 > 0.05
- alert: HighErrorRate
expr: job:error_rate:5m > 0.05
for: 3m # 持续 3 分钟(约 3 个采集周期)才触发告警
关键提醒:时间范围选择器
[5m] 中的 5m 是 Prometheus 服务端在查询时动态计算的,与 Prometheus 的 scrape_interval(采集间隔)无关。但为了数据准确性,建议 [5m] 至少包含 3 个以上的采集样本点。例如采集间隔为 15s 时,5m 窗口包含 20 个样本,足够稳定。
3.7 本章小结
PromQL 是 Prometheus 指标驱动策略的“翻译器”。通过本章学习,你应掌握:
- 即时查询与范围查询的区别,以及范围选择器
[d]的正确用法。 - 标签选择器的四种匹配模式,以及如何通过
by/without控制聚合维度。 rate()、irate()、increase()的适用场景与选择原则。- 降级熔断场景中常用的 PromQL 模式,以及时间窗口对灵敏度的影响。