3. PromQL 入门:Prometheus 数据模型、标签匹配与常用函数
PromQL(Prometheus Query Language)是 Prometheus 生态的核心查询语言,也是将原始指标数据转化为报警规则与可视化面板的基础。本节从数据模型出发,逐步讲解标签匹配机制与三个最常用的计算函数:rate、increase 和 histogram_quantile。
3.1 Prometheus 数据模型
Prometheus 存储的所有时间序列由 指标名称 和一组 标签(Label) 唯一标识。理解这一模型是编写正确 PromQL 的前提。
| 概念 | 说明 | 示例 |
|---|---|---|
| Metric Name | 描述被监控对象的一般含义 | http_requests_total |
| Label | 键值对,用于区分同一指标的不同维度 | method="GET", status="200" |
| Sample | 一个时间点上的具体数值 | @timestamp 1234.56 |
| Time Series | 同一 Metric + 同一 Label 组合的样本流 | http_requests_total{method="GET",status="200"} |
http_requests_total{job="api-server", instance="10.0.1.5:9090", method="POST", status="500"} = 7 @ 1710000000
其中 http_requests_total 是指标名,{job, instance, method, status} 是标签集合,7 是样本值,1710000000 是时间戳。
3.2 标签匹配与选择器
PromQL 使用 标签匹配器(Label Matcher) 来筛选时间序列。匹配器写在花括号 {} 内,支持四种操作符:
| 匹配器 | 含义 | 示例 | 匹配结果 |
|---|---|---|---|
= | 精确相等 | {status="200"} | 仅 status 为 "200" 的序列 |
!= | 不相等 | {status!="500"} | 排除 status 为 "500" 的序列 |
=~ | 正则匹配 | {method=~"GET|POST"} | method 为 GET 或 POST 的序列 |
!~ | 正则排除 | {method!~"DELETE|PUT"} | 排除 method 为 DELETE 或 PUT 的序列 |
=~ 和 !~)比精确匹配消耗更多计算资源。在报警规则和仪表盘查询中,优先使用 = 和 !=,仅在需要模糊匹配时使用正则。
选择器示例:
# 精确匹配:查询所有 GET 请求的 200 响应总数
http_requests_total{method="GET", status="200"}
# 正则匹配:查询所有 4xx 或 5xx 状态码的请求
http_requests_total{status=~"4[0-9]{2}|5[0-9]{2}"}
# 多标签组合:查询生产环境 api 实例的 POST 请求
http_requests_total{job="api-prod", instance=~"10\\.0\\..*", method="POST"}
3.3 常用函数:rate、increase 与 histogram_quantile
Prometheus 的 Counter 类型指标(如 http_requests_total)是单调递增的累计值,直接使用原始值没有意义。必须通过 rate 或 increase 函数将其转换为每秒速率或增量,才能反映真实变化。
3.3.1 rate() — 计算每秒平均增长率
rate(v range-vector) 计算时间范围内 Counter 指标的 每秒平均增长率。它是报警规则中最常用的函数,适用于检测突增或突降。
# 计算过去 5 分钟内,每秒平均请求数
rate(http_requests_total{status="500"}[5m])
# 在报警规则中使用:当 5xx 错误率超过 10 qps 时触发
rate(http_requests_total{status=~"5.."}[5m]) > 10
rate 的时间窗口建议设置为 1m、5m 或 10m。窗口太短(如 30s)容易抖动,太长(如 30m)会延迟报警响应。仪表盘面板通常使用 $__rate_interval 变量自动适配。
3.3.2 increase() — 计算时间范围内的增量
increase(v range-vector) 返回 Counter 在指定时间范围内的 总增量。与 rate 不同,它不除以时间秒数,直接给出原始增长值。
# 过去 1 小时内,总共发生了多少次 500 错误
increase(http_requests_total{status="500"}[1h])
# 对比:过去 5 分钟的总请求增量
increase(http_requests_total[5m])
| 函数 | 输出单位 | 适用场景 | 报警规则示例 |
|---|---|---|---|
rate() | 每秒速率(qps) | 实时流量监控、突增检测 | rate(errors[5m]) > 5 |
increase() | 原始增量(count) | 周期汇总、容量规划 | increase(errors[1h]) > 1000 |
rate 或 increase,它们只适用于 Counter。Gauge 指标(如 CPU 使用率、内存占用)应直接使用 avg_over_time 或 max_over_time 等聚合函数。
3.3.3 histogram_quantile() — 计算分位数
histogram_quantile(φ, bucket) 从 Histogram 类型的指标中计算 分位数(如 P50、P90、P99)。它需要配合 rate 或 increase 使用,将累积桶转换为速率后再计算。
# 计算过去 5 分钟内,请求延迟的 P99 值(单位:秒)
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))
# 计算 P50 和 P90
histogram_quantile(0.50, rate(http_request_duration_seconds_bucket[5m]))
histogram_quantile(0.90, rate(http_request_duration_seconds_bucket[5m]))
- P50(中位数): 50% 的请求延迟低于此值,反映典型体验。
- P90: 90% 的请求延迟低于此值,排除长尾影响。
- P99: 99% 的请求延迟低于此值,用于捕捉极端慢请求。
在报警规则中,通常对 P99 设置阈值,例如:histogram_quantile(0.99, rate(...)) > 2.0 表示 P99 延迟超过 2 秒时报警。
3.4 综合示例:构建一个延迟报警规则
将本节知识点串联起来,编写一个完整的 PromQL 报警规则:
# 报警规则:P99 延迟超过 2 秒,且持续 5 分钟
- alert: HighLatencyP99
expr: |
histogram_quantile(0.99,
rate(http_request_duration_seconds_bucket{job="api-server"}[5m])
) > 2.0
for: 5m
labels:
severity: critical
annotations:
summary: "API 服务 P99 延迟超过 2 秒 (当前值: {{ $value | humanizeDuration }})"
rate(...[5m])— 将 Histogram 桶转换为每秒速率。histogram_quantile(0.99, ...)— 从速率桶中计算 P99 分位数。> 2.0— 阈值条件:P99 延迟超过 2 秒。for: 5m— 持续 5 分钟满足条件才触发报警,避免毛刺误报。