4、PromQL入门:基本查询语法、选择器、时间范围、瞬时向量与区间向量,以及常用函数(rate、irate、increase等)
PromQL(Prometheus Query Language)是Prometheus内置的数据查询语言,它不仅是Grafana面板数据可视化的核心驱动,更是日常监控排障、告警规则编写、容量评估的基石。与SQL或LogQL不同,PromQL是围绕时序数据模型设计的,其核心操作对象是带有标签(Label)的指标(Metric)及其随时间变化的数据点。本章将从基本语法出发,深入剖析选择器、时间范围、瞬时向量与区间向量的本质区别,并重点讲解rate、irate、increase等常用函数的适用场景与底层逻辑,帮助学员建立扎实的查询思维。
上图展示了PromQL查询的核心链路:从时序数据库出发,通过选择器筛选目标序列,结合时间范围确定数据窗口,最终得到瞬时向量或区间向量,再经由函数加工后用于图表展示或告警判定。下面我们将逐一拆解每个环节。
4.1 基本查询语法与选择器
核心原理
PromQL的查询表达式由指标名和标签选择器组成。指标名用于定位具体的监控项(如 http_requests_total),而标签选择器则用于过滤出符合特定维度条件的序列。一个完整的查询表达式形如:http_requests_total{status="500", method="GET"}。其中花括号内的部分就是标签选择器,它支持四种匹配操作:=(精确匹配)、!=(反向精确匹配)、=~(正则匹配)、!~(反向正则匹配)。
判断方法或操作流程
在实际使用中,选择器的编写遵循以下步骤:
- 确定指标名:通过
curl http://localhost:9090/api/v1/label/__name__/values或Grafana的Explore页面查看所有可用的指标名。 - 筛选必要标签:根据业务维度(如实例、接口、状态码)添加标签条件。例如,要查看所有非200状态码的请求,可使用
http_requests_total{status!="200"}。 - 使用正则处理复杂维度:当需要匹配多个值或模糊匹配时,使用正则。例如
http_requests_total{handler=~"/api/v1/.*"}匹配所有以/api/v1/开头的接口。 - 注意空标签匹配:
{label=""}可以匹配到该标签不存在的序列,这在排查数据缺失时非常有用。
案例拆解或实战场景
假设我们有一个电商应用,需要监控不同支付渠道的成功率。指标为 payment_requests_total,标签包括 channel(alipay/wechat/card)和 result(success/failure)。要查询支付宝的成功请求数,表达式为:payment_requests_total{channel="alipay", result="success"}。若要同时查看支付宝和微信的失败请求,可使用正则:payment_requests_total{channel=~"alipay|wechat", result="failure"}。这种精确的维度筛选是后续计算成功率的基础。
常见误区或总结复盘
此外,注意标签值中的特殊字符(如点号、斜杠)在正则中需要转义。例如匹配 /api/v1 应写为 handler=~"/api/v1/.*",而不是 handler="/api/v1"(后者是精确匹配,不会匹配到带路径参数的序列)。
4.2 时间范围与向量类型
核心原理
PromQL查询分为瞬时查询和范围查询。瞬时查询返回的是查询时刻(或指定时间点)的数据,结果为瞬时向量(Instant Vector),每个时间序列只有一个样本值。范围查询则返回一个时间窗口内的所有样本,结果为区间向量(Range Vector),每个序列包含多个按时间排序的样本点。范围查询通过在指标选择器后添加方括号实现,如 http_requests_total[5m] 表示查询过去5分钟内的所有数据点。
判断方法或操作流程
选择瞬时还是区间向量,取决于后续操作:
- 如果只是查看当前值(如当前CPU使用率),使用瞬时向量。
- 如果需要计算速率、增量或进行趋势分析,必须使用区间向量作为函数输入。
- 在Grafana面板中,通常由面板的“查询类型”设置决定,但理解底层差异有助于调试。
时间范围的选择需考虑采集间隔。例如,若采集间隔为15秒,[5m] 窗口内约有20个样本点,足以计算稳定的速率;而 [1m] 只有4个样本,计算出的速率波动会很大。
案例拆解或实战场景
假设我们要监控Nginx的QPS(每秒请求数)。原始指标为 nginx_http_requests_total(Counter类型)。直接查询该指标只能看到累计值,无法反映当前速率。正确的做法是使用 rate(nginx_http_requests_total[5m])。这里 [5m] 指定了区间向量,rate 函数计算该窗口内每秒平均增长率。如果改用 irate(nginx_http_requests_total[5m]),则计算的是窗口内最后两个样本点的瞬时速率,对突发流量更敏感,但曲线更尖锐。
常见误区或总结复盘
rate 函数可能因样本不足而返回 NaN 或产生剧烈抖动。同时,过长的窗口(如 [1h])会平滑掉短时突刺,不利于告警检测。
另一个常见误区是混淆 increase 与 rate。 increase(v[5m]) 返回窗口内Counter的增量值(如5分钟内请求增加了多少次),而 rate 返回的是每秒平均速率。两者关系为:increase(v[5m]) = rate(v[5m]) * 300(300秒)。在告警规则中,若需要判断“5分钟内错误数超过100”,应使用 increase(errors_total[5m]) > 100,而不是 rate。
4.3 常用函数:rate、irate、increase 深度解析
核心原理
这三个函数均用于处理Counter类型指标(只增不减的累计值)。rate 计算区间向量在指定时间窗口内的每秒平均增长率,其算法是:取窗口内第一个和最后一个样本值,计算差值并除以时间差(秒)。irate 计算的是瞬时增长率,它仅使用窗口内最后两个样本点,计算它们的差值除以时间差。increase 则直接返回窗口内Counter的增量值(即最后一个值减去第一个值)。
判断方法或操作流程
选择哪个函数,取决于监控目标:
| 函数 | 输出含义 | 适用场景 | 特点 |
|---|---|---|---|
rate() | 每秒平均速率 | 长期趋势、告警阈值(如QPS > 1000) | 平滑,抗抖动,适合稳定指标 |
irate() | 每秒瞬时速率 | 突发流量检测、短时峰值分析 | 灵敏,反映最新变化,但曲线毛刺多 |
increase() | 窗口内总增量 | 统计总量(如5分钟错误数) | 直观,适合与固定阈值比较 |
案例拆解或实战场景
我们以CPU使用率监控为例。假设指标 node_cpu_seconds_total 是Counter类型,标签 mode 区分cpu、idle、user等。要计算CPU使用率,需先计算非空闲时间的速率,再除以总时间速率:
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
这里使用 rate 是因为CPU使用率是连续变化的,需要平滑的平均值。若改用 irate,则曲线会频繁跳动,不利于观察整体趋势。而在告警规则中,若希望快速响应CPU飙高,可使用 irate 设置短窗口(如 [1m])来捕捉瞬时尖峰。
常见误区或总结复盘
rate 和 increase 计算出现负值或异常跳变。Prometheus的 rate 函数会自动处理Counter重置(检测到值下降时,按从零开始计算),但 increase 在遇到重置时可能会返回错误结果。因此,在涉及可能重置的Counter时,优先使用 rate 或 irate。
另外,irate 对样本间隔非常敏感。如果采集间隔不规律(如某些实例延迟上报),irate 可能产生极端值。此时应使用 rate 并适当增大窗口来平滑数据。最后,所有函数都要求输入是区间向量,如果误传瞬时向量,查询会报错。
4.4 综合实战:构建一个完整的监控查询
核心原理
将选择器、时间范围、函数和聚合操作(如 sum、avg、by)组合,可以构建复杂的监控查询。聚合操作允许我们按标签维度合并多个序列,例如按实例汇总所有接口的请求速率。
操作流程
假设我们要监控一个微服务集群的总QPS,并按实例维度拆分。步骤如下:
- 确定基础指标:
http_requests_total(Counter,标签:instance、path、method)。 - 计算每个序列的速率:
rate(http_requests_total[5m])。 - 按实例聚合:
sum by (instance) (rate(http_requests_total[5m]))。 - 若需总QPS:去掉
by子句,直接sum(rate(http_requests_total[5m]))。
案例拆解
某次故障排查中,我们发现支付接口响应时间上升。通过Grafana查询:histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket{path="/api/pay"}[5m]))),得到95分位延迟。同时,用 sum by (instance) (rate(http_requests_total{path="/api/pay", status="500"}[5m])) 查看错误率。通过对比发现,错误率集中在某个实例,进一步定位到该实例的磁盘IO瓶颈。这个案例展示了PromQL从全局到局部、从现象到根因的排查路径。
常见误区或总结复盘
by 子句保留必要维度;3) 在Grafana中调试时,先用Explore页面验证查询结果,再创建面板;4) 对于高基数标签(如 path 包含用户ID),应提前设计标签降基方案。
最后,建议在团队内建立PromQL查询规范,例如:统一使用 rate 而非 irate 作为默认速率函数;所有告警规则必须使用 for 子句设置持续时间,避免瞬时抖动误报;定期审查慢查询,利用 label_replace 或Recording Rule优化复杂表达式。掌握PromQL不仅是语法学习,更是监控思维的建设过程。