【监控】PromQL 查询语言
PromQL(Prometheus Query Language)是 Prometheus 内置的强大查询语言,用于从时间序列数据中筛选、聚合和计算指标。它是 Prometheus 生态的核心工具,广泛用于监控数据查询、可视化(如 Grafana)和告警规则定义。以下是 PromQL 的核心概念和常见用法:
一、基本数据类型
PromQL 处理以下四种数据类型:
- 瞬时向量(Instant Vector)
- 同一时间戳的一组时间序列,每个序列包含一个样本值。
- 例如:
node_cpu_seconds_total{mode="idle"}
(当前所有 CPU 的空闲时间)。
- 范围向量(Range Vector)
- 一段时间内的一组时间序列,每个序列包含多个样本值。
- 例如:
node_cpu_seconds_total{mode="idle"}[5m]
(过去 5 分钟的 CPU 空闲时间)。
- 标量(Scalar)
- 单个浮点数值,如
10.5
或计算结果(如count(node_cpu_seconds_total)
)。
- 单个浮点数值,如
- 字符串(String)
- 文本值(目前较少使用,主要用于标签匹配)。
二、核心查询语法
1. 选择器(Selector)
从时间序列中筛选特定指标:
# 基本形式:指标名[{}]
node_cpu_seconds_total{} # 选择所有 CPU 时间序列# 通过标签过滤
node_cpu_seconds_total{mode="user", cpu="0"} # 仅选择 CPU0 的用户态时间# 正则匹配
http_requests_total{status=~"5.."} # 匹配状态码以 5 开头的请求
2. 时间范围选择
使用 []
指定时间范围,结合 @
指定时间点:
node_cpu_seconds_total{mode="idle"}[5m] # 过去 5 分钟的数据
node_cpu_seconds_total{mode="idle"}[1h] # 过去 1 小时的数据
node_cpu_seconds_total{mode="idle"}[5m] @ 1621000000 # 特定时间点的 5 分钟数据
3. 时间位移操作
使用 offset
关键字获取历史数据:
node_cpu_seconds_total{mode="idle"} offset 1d # 获取 1 天前的当前时间点数据
rate(node_cpu_seconds_total{mode="idle"}[5m] offset 30m) # 获取 30 分钟前的 5 分钟 CPU 使用率
三、常用函数
1. 聚合函数
对多个时间序列进行聚合计算:
sum(node_cpu_seconds_total{mode="idle"}) # 所有 CPU 空闲时间总和
avg(node_memory_usage_bytes) # 平均内存使用量
count(node_cpu_seconds_total) # CPU 核心总数
max(node_load1) # 最大系统负载
min(node_network_receive_bytes_total) # 最小网络接收流量
topk(5, node_disk_usage_bytes) # 按磁盘使用量排序的前 5 个
2. 速率计算
计算时间序列的变化率(常用于计数器类型指标):
rate(node_cpu_seconds_total{mode="user"}[5m]) # 5 分钟内 CPU 用户态时间的平均变化率
irate(node_http_requests_total[1m]) # 1 分钟内 HTTP 请求的瞬时变化率(对尖峰更敏感)
increase(node_cpu_seconds_total{mode="user"}[1h]) # 1 小时内 CPU 用户态时间的总增加量
3. 时间窗口函数
对时间窗口内的数据进行统计:
avg_over_time(node_cpu_usage_percent[5m]) # 5 分钟内 CPU 使用率的平均值
max_over_time(node_load1[1h]) # 1 小时内系统负载的最大值
min_over_time(node_disk_free_bytes[1d]) # 1 天内磁盘空闲空间的最小值
4. 数学与逻辑函数
abs(-5) # 绝对值:5
sqrt(node_memory_usage_bytes) # 平方根
ceil(node_cpu_usage_percent) # 向上取整
floor(node_cpu_usage_percent) # 向下取整
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) # 计算 95% 分位数
四、运算符
1. 算术运算符
node_memory_used_bytes / node_memory_total_bytes * 100 # 内存使用率百分比
rate(node_network_receive_bytes_total[5m]) / 1024 / 1024 # 网络接收速率(MB/s)
2. 比较运算符
node_cpu_usage_percent > 80 # 筛选 CPU 使用率超过 80% 的时间序列
node_disk_free_bytes < 1073741824 # 筛选磁盘空闲空间不足 1GB 的时间序列
3. 逻辑运算符(向量间)
up and node_cpu_usage_percent < 50 # 同时满足服务正常(up=1)且 CPU 使用率低于 50%
http_requests_total{method="GET"} or http_requests_total{method="POST"} # 合并 GET 和 POST 请求
4. 聚合操作符
sum(node_memory_usage_bytes) by (instance) # 按实例聚合内存使用量
avg(node_cpu_usage_percent) without (cpu) # 排除 CPU 标签后的平均使用率
五、高级用法
1. 直方图与分位数
Prometheus 使用直方图(Histogram)统计请求耗时等分布数据:
# 计算 HTTP 请求耗时的 95% 分位数(需先计算速率)
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
2. 向量匹配
处理两个向量间的运算(如计算错误率):
# 计算每个服务的 HTTP 错误率(5xx 状态码请求数 / 总请求数)
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)/
sum(rate(http_requests_total[5m])) by (service)
3. 时间序列相关性分析
例如,找出内存使用率与 CPU 使用率同时升高的实例:
node_memory_usage_percent > 80 and on (instance) node_cpu_usage_percent > 70
六、常见查询示例
- 计算 CPU 使用率(百分比):
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
- 计算内存使用率(百分比):
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100
- 查找最繁忙的 3 个磁盘(按 IO 速率):
topk(3, rate(node_disk_io_time_seconds_total[5m]))
- 计算服务可用性(基于 HTTP 请求成功率):
100 * (1 - sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])))
七、性能优化建议
- 避免全量查询:
优先使用标签过滤(如{job="api"}
),避免查询所有时间序列。 - 控制时间范围:
使用[5m]
、[1h]
等限制查询的数据量,避免查询过长时间范围。 - 缓存常用计算:
对于复杂计算,考虑使用 Prometheus 的recording rules
预计算并存储结果。 - **谨慎使用 **
irate()
:
irate()
对尖峰敏感,适合告警;但在可视化时,rate()
通常更平滑。
八、学习资源
- 官方文档:PromQL 官方文档
- Grafana 教程:在 Grafana 中实践 PromQL 查询
- Prometheus 实战(书籍):第 4 章详细讲解 PromQL
通过掌握 PromQL,你可以从 Prometheus 中挖掘出更有价值的监控数据,为系统优化和故障排查提供支持!