PromQL 极简指南:把监控数据玩出花

从看懂 Grafana 图表,到自己写出 P95 延迟查询

March 22, 2026·2 min read·Yimin
#监控#可观测性#Prometheus#Grafana#PromQL

当后端系统上线后,我们最怕的不是报错,而是两眼一抹黑。学会读懂和编写 PromQL,是你从“碰运气排障”跨越到“精准把脉系统状态”的关键一步。

🎯 为什么老是看不懂 PromQL?

每次打开 Grafana,想改一改某个图表的查询条件,总会看到类似这样一长串的“咒语”:

histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

这是因为 Prometheus 存储数据的方式跟我们熟悉的 MySQL 关系型数据库完全不一样。它存的是时间序列数据(Time Series Data)。简单来说,它不是记下“某时某刻发生了一次请求”,而是记录“在这个时刻,请求的总数变成了 100”。

这套查询语言叫做 PromQL(Prometheus Query Language),它的核心逻辑是对时间轴上的数据点进行数学计算(求和、求速率、求分位数)。


🧠 核心概念:标签(Labels)与过滤器

在 PromQL 中,指标的维度是通过 标签(Labels) 来区分的。

http_requests_total{model="gpt-4o", status="200"}

这里 http_requests_total 是指标名称(一个一直在往上涨的计数器),而 {} 里面的内容就是过滤器。这句话的意思是:只给我看使用了 gpt-4o 并且状态码是 200 的请求总数。

这就像 SQL 里面的 WHERE model='gpt-4o' AND status='200'


🔍 掌握这 5 把斧,搞定 90% 的监控需求

日常排查问题,你根本不需要背下几百个函数,只要搞懂下面这 5 个最高频的用法,就能看懂绝大多数的 Grafana 面板。

1. 计算 QPS(请求速率)—— rate()

只看请求总数没有意义,我们通常想知道的是**“每秒钟系统承载了多少请求”**。

rate(http_requests_total[1m])
  • [1m]:代表时间窗口(过去 1 分钟)。
  • 作用:计算过去 1 分钟内,这个计数器每秒平均增长了多少。
  • 场景:画出早晚高峰的流量曲线。

2. 聚合求和(按维度分组)—— sum by

如果直接对包含几百个容器的系统求 rate,图表上会出现密密麻麻几百条线(每种标签组合都是一条线)。此时我们需要把它们合并

sum by (client) (rate(http_requests_total[1m]))
  • 作用:把结果按照 client 这个标签进行分组,并把其他标签全丢掉、数值加起来。
  • 等价于:SQL 中的 GROUP BY client
  • 场景:老板问你“最近一分钟各个业务线的 QPS 是多少?”,用它准没错。

3. 计算一段时间内的增量 —— increase()

有时候我们不关心每秒的速率,只想知道过去一段时间总共发生了多少次。

sum by (model) (increase(http_requests_total[24h]))
  • 作用:计算过去 24 小时内,各个模型的请求量一共增长了多少次
  • 场景:查看今天全天的调用总量、或者刚刚过去的 5 分钟我测试了多少次接口。

4. 衡量真实的性能体验 —— histogram_quantile()

这是最有技术含量、也最让人头大的一个。为什么要用它?因为**“平均延迟”是一个撒谎的指标**。

假设 99 个请求都是 10ms,有 1 个请求卡了 10 秒。平均延迟看起来依然很低,但那个卡了 10 秒的用户体验极差。我们需要的是 P95 延迟(95% 的请求都在多少毫秒内完成的)。

histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
  • http_request_duration_seconds_bucket:Prometheus 把延迟分成了很多个桶(比如 0.1秒的桶,0.5秒的桶),这个指标记录了落入每个桶的请求数量。
  • le (less than or equal):就是“小于等于某耗时”的那个桶的标签。
  • histogram_quantile(0.95, ...):基于这些桶的分布,估算出 95 分位数的具体时间。
  • 场景:评估后端系统的真实服务质量(SLA)。

5. 计算错误率比例

怎么知道系统现在的健康度?用错误请求速率除以总请求速率

  sum(rate(http_requests_total{status=~"5.."}[1m])) 
/ 
  sum(rate(http_requests_total[1m]))
  • status=~"5..":这里用到了正则表达式(=~),匹配所有以 5 开头的状态码(500, 502, 504)。
  • 场景:配合 Grafana 的报警功能,当错误率超过 1% 时自动推送到飞书/钉钉群。

⚠️ 新手避坑指南

  1. 别拿 rate() 画总数图rate 算出来的是“每秒增量”,如果你的系统请求量很低,一分钟只有 2 个请求,那 rate(xxx[1m]) 画出来的线只有 0.03左右,你可能会以为数据丢了。看总增量用 increase()
  2. 时间窗口别设得比采集间隔还小:如果你的 Prometheus 每 15 秒抓取一次数据,你写 rate(xxx[10s]) 是算不出东西的,至少得涵盖两个数据点。
  3. 标签要克制:不要把随机生成的 x-request-id 作为 Label 打到指标里!这会导致“高基数(High Cardinality)”问题,瞬间撑爆 Prometheus 的内存。

📝 总结

PromQL 并不是什么神秘的魔法。理解了它的时序特性,熟记 rate(看速率)、increase(看总量)、sum by(分组)和 histogram_quantile(看分位耗时),你就能在排查性能瓶颈、规划容量时拥有上帝视角。

下次再面对慢查询或者流量突增,不妨打开 Grafana 的 Explore 页面,敲下自己的第一行 PromQL 吧!