PromSL详解
PromQL(Prometheus Query Language)是Prometheus监控系统的核心查询语言,专门用于处理时间序列数据。下面通过一个表格快速了解其核心概念:
|
特性分类 |
核心概念 |
说明 |
|---|---|---|
|
数据模型 |
时间序列 (Time Series) |
由指标名称(Metric Name)和一组标签(Label)唯一标识的数据点序列,格式为 |
|
指标类型 (Metric Types) |
主要包括: - Histogram(直方图) & Summary(摘要):用于统计和分析数据的分布情况 |
|
|
查询操作 |
即时向量 (Instant Vector) |
每个时间序列只包含单个最新数据点的查询结果 |
|
范围向量 (Range Vector) |
包含一个时间范围内所有数据点的查询结果 |
|
|
匹配模式 |
支持完全匹配( |
|
|
功能与应用 |
聚合运算 (Aggregation) |
支持使用 |
|
应用场景 |
用于临时数据查询与调试、Grafana等工具中的数据可视化、以及定义告警规则 |
一. 核心概念
理解 PromQL 前,需要先了解其数据模型和基本数据类型
1.数据模型:Prometheus 的数据由时间序列(Time Series) 组成,每条序列由指标名称(Metric Name)、标签(Label)、以及一系列的样本(Sample)(即 (timestamp, value) 数据点)构成。其格式通常为 <metric_name>{<label_name>=<label_value>, ...},例如 http_requests_total{method="GET", status="200", instance="localhost:9090"}
2.指标类型:
- Counter(计数器):只增不减的累积指标,如 HTTP 请求总数、CPU 使用时间。适用于统计累计值和计算速率。
- Gauge(仪表盘):可任意变化的瞬时指标,如内存使用量、CPU 使用率、温度。适用于反映当前状态。
- Histogram(直方图)& Summary(摘要):用于统计和分析数据的分布情况,如请求延迟。
3.数据类型:PromQL 表达式操作或计算后,主要会产生以下几种类型的结果:
- Instant Vector(瞬时向量):同一时间戳下的一组时间序列,每个序列包含最新的一个样本值。例如
http_requests_total。 - Range vector(范围向量):一段时间范围内的一组时间序列,每个序列包含多个样本值。例如
http_requests_total[5m]。范围向量不能直接图表化,需借助函数处理。 - Scalar(标量):一个简单的浮点数值,如 10。
- String(字符串):简单的字符串值(在 PromQL 中较少使用)
二. 查询操作
PromQL 提供了强大的选择器和操作符来查询和操作时间序列数据
1.时间序列选择器
- 瞬时向量选择器:直接使用指标名称或通过
{}和标签进行过滤。
http_requests_total # 查询所有时间序列 http_requests_total{method="GET"} # 完全匹配标签 http_requests_total{status=~"5.."} # 正则匹配标签:状态码为5xx的请求 http_requests_total{environment=""} # 匹配缺少该标签的时间序列
- 范围向量选择器:在瞬时向量选择器后附加
[<时长>]来查询一段时间内的数据。
http_requests_total[5m] # 过去5分钟的所有样本 node_cpu_seconds_total{mode="idle"}[1h] # 过去1小时CPU空闲时间
# 支持的时间单位:s(秒),m(分钟),h(小时),d(天),w(周),y(年)
- 偏移修饰符(Offset):使用
offset关键字查询历史数据
http_requests_total offset 5m # 查询5分钟前的瞬时数据
http_requests_total[1d] offset 1d # 查询昨天一天的数据
2.操作符
PromQL 支持丰富的操作符来对数据进行运算和比较。
- 算术运算符:
+,-,*,/,%,^(幂运算)
# 计算内存使用率 (node_memory_MemTotal_bytes - node_memory_MemFree_bytes) / node_memory_MemTotal_bytes * 100
- 比较运算符:
==,!=,>,<,>=,<=
up == 1 # 筛选状态为 "up" 的实例
- 逻辑/集合运算符:
and,or,unless
# 找出请求量高且错误率也高的实例 rate(http_requests_total[5m]) > 100 and rate(http_errors_total[5m]) > 1
- 聚合运算符:
sum,min,max,avg,stddev,stdvar,count,group。常与by或without结合使用,以指定根据哪些标签进行分组聚合或排除哪些标签进行聚合。
# 按 job 分组计算请求总量 sum by(job) (http_requests_total) # 计算所有实例的请求总量,忽略 instance 标签 sum without(instance) (http_requests_total)
三. 常用函数
PromQL 提供了大量内置函数来处理时间序列数据。
|
函数类型 |
函数名 |
说明 |
示例 |
|---|---|---|---|
|
速率计算 |
|
计算范围向量中时间序列的平均每秒增长率,自动处理计数器重置 |
|
|
|
计算范围向量中时间序列的瞬时每秒增长率(基于最后两个样本),对变化更敏感 |
|
|
|
|
计算范围向量中时间序列的指定时间范围内的总增量,自动处理计数器重置 |
|
|
|
聚合函数 |
|
对时间序列的值求和 |
|
|
|
对时间序列的值求平均值 |
|
|
|
|
找出一组时间序列中的最大值或最小值 |
|
|
|
|
统计时间序列的数量 |
|
|
|
|
返回样本值最大的 k 条时间序列 |
|
|
|
时间聚合 |
|
计算指定时间范围内每个时间序列的平均值 |
|
|
分位数计算 |
|
根据直方图指标计算分位数 (φ ∈ [0,1]) |
|
|
数据处理 |
|
如果具有指定名称和标签的时间序列不存在,则返回空向量,常用于检测指标是否存在 |
|
|
预测 |
|
基于历史数据预测时间序列未来的值 |
|
四. 实战示例
1.计算CPU使用率
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) # rate(node_cpu_seconds_total{mode="idle"}[5m])计算每个实例过去5分钟的平均空闲率,avg by(instance)按实例聚合,最后用 100 - ... * 100得到使用率百分比
2.计算HTTP请求错误率(5xx)
sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100 # 先计算状态码为5xx的请求速率和总请求速率,相除后乘以100得到错误率百分比
3.计算P99请求延迟
histogram_quantile(0.99, sum by(le) (rate(http_request_duration_seconds_bucket[5m]))) # 对直方图指标 http_request_duration_seconds_bucket在5分钟内的增长率按 le(桶边界) 分组求和,然后计算99分位数
4.检查实例是否存活
up == 1 # up指标为1表示实例健康,为0表示不健康
5.预测磁盘空间耗尽时间
predict_linear(node_filesystem_free_bytes{device="/dev/sda1"}[6h], 3600) / (1024 * 1024)
# 基于过去6小时的数据,预测1小时后的磁盘剩余空间(MB)
五. 补充概念
1. 分位数quantile
|
分位数类型 |
含义 |
常见应用场景 |
|---|---|---|
|
中位数 (Median) |
将数据分为两等份的点,即50%的数据低于此值。 |
代表数据的“一般水平”,比平均值更能抵抗极端值的干扰。例如,居民收入中位数。 |
|
四分位数 (Quartile) |
将数据分为四等份的三个点,包括下四分位数 (Q1, 25%)、中位数 (Q2, 50%) 和上四分位数 (Q3, 75%) |
用于绘制箱线图,直观展示数据分布范围和中位数,并识别异常值。 |
|
百分位数 (Percentile) |
将数据分为一百等份的点,例如第5百分位数表示有5%的数据低于此值。 |
用于评估排名,如考试成绩的百分位数可以反映你在全体考生中的位置。 |
2. 时间序列(Time Series) & 时间序列标识符 & 样本(Sample)
在时间序列的标识符(即 <metric_name>{<label_name>=<label_value>, ...}这个格式)中,确实不包含时间戳。这个格式定义的是一条唯一的时间序列,而时间维度体现在这条序列所包含的一系列样本(Sample) 上。
|
概念要素 |
角色与内容 |
类比理解 |
|---|---|---|
|
时间序列标识符 |
定义“谁”: |
就像一个人的身份证号或姓名+住址,它唯一地确定了这个人,但这个身份信息本身不包含这个人随时间变化的动态信息(如身高、体重)。 |
|
样本(Sample) |
记录“何时”与“何值”: |
就像为这个人建立的成长记录,例如 |
|
时间序列(Time Series) |
完整的“生命轨迹”: |
身份 + 全部历史记录 就构成了这个人完整的、随时间变化的生命轨迹。 |
如下是一个具体例子
假设我们监控一个服务的HTTP请求,有一条时间序列的标识符是:
http_requests_total{job="api-server", method="GET", status="200"}
这条序列在时间线上可能会有一系列样本点,例如:
-
(...上面相同的标识符...) => 1024 (t₀)// 在 t₀ 时刻,总请求数是1024 -
(...上面相同的标识符...) => 1025 (t₁)// 在 t₁ 时刻,总请求数增长到1025 -
(...上面相同的标识符...) => 1026 (t₂)// 在 t₂ 时刻,总请求数增长到1026
这里的 t₀, t₁, t₂就是具体的时间戳。标识符 http_requests_total{...}定义了这条数据线的“身份”,而一系列带时间戳的样本点 (t₀, 1024), (t₁, 1025), (t₂, 1026)则共同描绘出这条数据线随时间变化的轨迹
Prometheus的存储视角
从Prometheus数据库(TSDB)的内部来看,它的存储结构也清晰地反映了这种关系:
-
索引(Index):主要用于快速查找。它记录了“哪组标签(即时间序列标识符)对应哪个内部ID”。
-
数据块(Chunks):实际存储样本点的地方。每个数据块包含了一段时间范围内某条时间序列的所有
(timestamp, value)对。
所以,当您查询 http_requests_total{job="api-server"}过去5分钟的数据时,Prometheus会先通过索引找到所有匹配的序列ID,然后去对应的数据块中读取这些序列在最近5分钟内的所有样本值
posted on 2025-10-09 12:06 Karlkiller 阅读(19) 评论(0) 收藏 举报
浙公网安备 33010602011771号