11、prometheus-PromQL-5-聚合计算函数
PromQL聚合计算函数
promQL篇章: 表达式,豆包ai,偏移量修改器,指标类型,指标类型,聚合计算函数
本章重点,promQL进阶,by/without, on/ignoring,group_left/group_right
参考:豆包ai+(prometheus实战个人总结)
一、聚合计算
-
单指标的局限性
在实际监控场景中,孤立的单指标样本值往往无法直接支撑决策:
- 集群场景:Web服务器集群包含20+实例时,逐个查看每个实例的响应时长,既低效又无法把握集群整体负载状态;
- 多维度场景:同一接口的请求量按“地域+终端类型”拆分后,单维度数据无法反映接口整体服务能力;
- 趋势分析:单时间点的CPU使用率无法判断负载是否持续升高。
-
聚合计算的核心价值
PromQL的聚合计算通过对多Target的同一指标、或同一指标的多维度数据进行联合统计,实现三大核心价值:
- 全局视角:汇总集群、服务级别的核心指标,如“微服务集群总请求量”“全机房内存使用率均值”;
- 维度钻取:按业务标签(如服务、地域、接口)分组聚合,定位问题根源,如“长沙地域5xx错误率最高的服务”;
- 趋势提炼:通过统计量(如均值、分位数)过滤瞬时波动,反映指标真实趋势,如“接口95分位响应时间”。
二、聚合函数:by/without
聚合函数的核心能力通过by和without子句实现标签分组,控制聚合后的结果标签,两者功能互补,可根据场景灵活选择。
-
语法格式: 聚合操作支持两种等价格式,推荐使用格式1(聚合函数后接分组子句),可读性更高:
# 格式1:聚合函数后接分组子句(推荐) <聚合函数>([参数, ]<即时向量表达式>)[without | by (标签列表)]# 格式2:分组子句嵌入聚合函数参数 <聚合函数>[without | by (标签列表)]([参数, ]<即时向量表达式>) -
by子句:指定分组标签
by (标签列表):仅保留指定标签作为分组依据,聚合后结果仅包含这些标签。适用于“明确知道需要保留哪些标签”的场景。
# 示例1:按instance分组,计算各实例的文件系统可用空间总和 sum(node_filesystem_avail_bytes) by (instance)# 示例2:按service和path分组,计算各接口的平均响应时间 avg(http_request_duration_seconds_sum / http_request_duration_seconds_count) by (service, path) -
without子句:排除标签分组
without (标签列表):删除指定标签,剩余标签作为分组依据。适用于“需要排除少数标签,保留大部分标签”的场景。
# 示例1:排除job标签,保留其他标签(如instance、mountpoint),计算可用空间总和 sum(node_filesystem_avail_bytes) without (device)# 示例2:排除cpu标签,计算各实例的CPU使用率均值 avg(irate(node_cpu_seconds_total{mode="user"}[5m])) without (cpu) -
关键注意事项
- 标签唯一性:聚合后的标签组合需唯一,否则会导致结果覆盖;
- 标量转换:若聚合后无分组标签(即全局聚合),返回结果为标量,可通过scalar()函数显式转换,如scalar(sum(http_requests_total));
- 嵌套聚合:支持聚合函数嵌套使用,如sum(avg(irate(…)) by (instance)),实现“先按实例聚合,再全局汇总”。
三、聚合函数全解析
PromQL内置11种聚合函数,仅支持作用于即时向量(不支持范围向量),返回结果为新的即时向量或标量。
3.1 聚合函数速查表
| 函数名 | 核心功能 | 返回类型 | 典型场景 | 关键备注 |
|---|---|---|---|---|
| sum() | 样本值求和 | 即时向量/标量 | 集群总资源使用、服务总请求量 | 支持多标签分组求和 |
| avg() | 样本值求平均 | 即时向量/标量 | 多实例指标均值、接口平均响应时间 | 受极端值影响,需结合分位数使用 |
| count() | 统计分组内时间序列数量 | 即时向量/标量 | 运行中实例数、异常接口数 | 统计“序列数”而非“样本值总和” |
| stddev() | 计算标准差 | 即时向量/标量 | 指标波动程度分析(如响应时间稳定性) | 值越大,数据波动越剧烈 |
| stdvar() | 计算方差 | 即时向量/标量 | 数据离散度评估(如负载均衡度) | 标准差的平方,反映整体离散程度 |
| min() | 取样本最小值 | 即时向量 | 最低可用内存、最小接口响应时间 | 返回对应最小值的时间序列 |
| max() | 取样本最大值 | 即时向量 | 最高CPU使用率、峰值网络吞吐量 | 返回对应最大值的时间序列 |
| topk(k, expr) | 返回前k个最大样本值的序列 | 即时向量 | 高负载实例排序、慢接口定位 | k为正整数,支持嵌套聚合 |
| bottomk(k, expr) | 返回前k个最小样本值的序列 | 即时向量 | 闲置资源识别、低请求量接口筛选 | k为正整数,可用于资源优化 |
| quantile(φ, expr) | 返回指定分位数的值(0≤φ≤1) | 即时向量/标量 | 响应时间分位值、负载分布分析 | φ=0.95常用作“用户体验基准” |
| count_values(lbl, expr) | 统计样本值的出现次数 | 即时向量 | 状态码分布、实例健康状态统计 | 返回标签为“样本值”、值为“次数”的向量 |
3.2 重点函数实战示例
以下示例基于常见监控指标(如node_exporter、http_exporter输出指标),覆盖不同业务场景,可直接复用或修改后使用。
3.2.1 sum():求和聚合的核心场景
-
说明
- sum()是最常用的聚合函数,核心用于“总量统计”,结合by/without子句可实现多维度分组求和。
- 语法格式:sum(即时向量表达式) [by (分组标签列表) | without (排除标签列表)]
-
示例
# 1. 统计服务器集群的物理CPU核心总数 count(sum(node_cpu_seconds_total) by (cpu))# 2. 统计5分钟内各微服务的HTTP请求总增量,按服务名分组 # increase()计算5分钟增量,sum()按service分组求和 sum(increase(http_requests_total[5m])) by (service)# 3. 计算所有实例的内存使用总量(总内存-空闲内存) sum(node_memory_MemTotal_bytes - node_memory_MemFree_bytes)
3.2.2 avg():均值统计的正确姿势
-
说明
- avg()用于计算多样本的平均值,适合“整体水平评估”,但需注意极端值对结果的影响,建议结合max()/min()使用。
-
示例
# 1. 统计不同机房API服务的平均网络延迟,按机房标签(room)分组 avg(net_response_time_seconds{job="api-service"}) by (room)# 2. 计算所有实例5分钟内的平均CPU使用率,排除空闲状态(mode="idle") # 说明:irate()计算瞬时速率,避免因Counter重置导致的误差 avg(irate(node_cpu_seconds_total{mode='idle'}[5m])) by (cpu) * 100
3.2.3 quantile():分位数的关键应用
-
说明
- quantile(φ, expr)是“用户体验监控”的核心函数,通过分位数过滤极端值,更贴近真实业务场景(如95%用户的响应时间)。
- 常见分位数场景:φ=0.5(中位数,反映整体分布中心)、φ=0.95(常用用户体验基准)、φ=0.99(极端场景基准)。
-
示例
# 1. 按服务分组,计算各服务的95分位响应时间(排除极端慢请求的干扰) # 响应时间=总耗时/请求数,再计算95分位值 quantile(0.95, http_request_duration_seconds_sum / http_request_duration_seconds_count) by (service)# 2. 磁盘使用率分布分析, 计算各挂载点的99分位磁盘使用率,评估极端情况下的磁盘压力 quantile(0.95,(node_filesystem_size_bytes - node_filesystem_free_bytes)/node_filesystem_size_bytes * 100) by (mountpoint)
3.2.4 topk()/bottomk():排序筛选实战
-
说明:
- topk()和bottomk()用于从大量序列中筛选“极值序列”,常用于问题定位和资源优化。
-
示例
# 1. 筛选CPU使用率前5的实例,定位高负载节点# 先计算各实例非空闲CPU速率总和,再取前5 topk(5,sum(irate(node_cpu_seconds_total{mode!='idle'}[5m])) by (instance))# 2. 筛选内存使用率最低的3个实例,判断是否存在闲置资源可优化 bottomk(3,(node_memory_MemTotal_bytes - node_memory_MemFree_bytes)/node_memory_MemTotal_bytes * 100)
3.2.5 count_values():状态分布统计
-
说明
- count_values(lbl, expr)用于统计“样本值的出现次数”,返回的向量标签为样本值,值为出现次数,适合状态分布分析。
-
示例
# 1. 统计200、404、500三种状态码的请求数分布,标签名为status_code count_values("status_code", http_requests_total{status_code=~"200|404|500"})# 2. 统计nodes任务下实例的健康状态(up=1为正常,up=0为异常) count_values("health_status", up{job="nodes"})
四、即时向量运算逻辑
PromQL支持两个即时向量间的算术运算(如加减乘除)、比较运算(如>、<),核心通过“向量匹配”规则确定两个向量的关联关系,分为“一对一匹配”和“一对多/多对一匹配”。
- 向量匹配核心概念
- 即时向量:包含多个时间序列,每个序列有唯一的标签组合和对应样本值;
- 匹配依据:通过标签组合匹配两个向量中的时间序列;
- 运算结果:匹配成功的序列执行运算,未匹配的序列被过滤。
4.1、一对一匹配
两个向量中“标签组合完全相同”的序列进行匹配,一对一执行运算。若标签不完全匹配,可通过ignoring(忽略指定标签)或on(仅保留指定标签)调整匹配范围。
-
语法格式
# 忽略指定标签进行匹配 <向量A> <运算符号> ignoring(<标签列表>) <向量B># 仅按指定标签进行匹配 <向量A> <运算符号> on(<标签列表>) <向量B> -
示例
# 1. 计算HTTP 500错误占总请求的比例,http_errors包含code标签,http_requests无code标签,需忽略code标签匹配 # 5分钟内500错误速率 / 总请求速率,忽略code标签 rate(http_errors{status_code="500"}[5m]) / ignoring(code) rate(http_requests[5m])# 2. 按instance标签匹配总内存和空闲内存,计算各实例内存使用率 # # (总内存-空闲内存)/总内存 *100,仅按instance标签匹配 (node_memory_MemTotal_bytes - node_memory_MemFree_bytes) / on(instance) node_memory_MemTotal_bytes * 100
4.3 一对多/多对一匹配
-
当一个向量中的一个序列可匹配另一个向量中的多个序列时
- group_left(左侧为“多”,右侧为“一”)
- group_right(右侧为“多”,左侧为“一”)
- 定“多”的一侧,实现一对多或多对一运算(左多就是多对一,右多就是一对多)
-
语法格式
# 左侧为多,右侧为一,忽略指定标签匹配 <向量A(多)> <运算符号> ignoring(<标签列表>) group_left <向量B(一)># 右侧为多,左侧为一,仅按指定标签匹配 <向量A(一)> <运算符号> on(<标签列表>) group_right <向量B(多)> -
示例
# 1. 算各状态码(200、404、500)的请求占总请求的比例,左侧http_requests_total按service和status_code分组(多序列),右侧按service分组(单序列) # 左侧多序列(service+status_code),右侧单序列(service),忽略status_code匹配 sum(rate(http_requests_total[5m])) by (service, status_code) / ignoring(status_code) group_left sum(rate(http_requests_total[5m])) by (service)# 2. 判断各实例CPU使用率是否超过所在区域的阈值,左侧为各实例使用率(多序列,含instance和region标签),右侧为区域阈值(单序列,含region标签) # 左侧多实例,右侧单区域阈值,按region标签匹配,右侧为多(通过group_right) sum(irate(node_cpu_seconds_total{mode!="idle"}[5m])) by (instance, region) > on(region) group_right instance region_cpu_threshold 这个值region_cpu_threshold需要在配置文件中定义- job_name: 'custom_thresholds'static_configs:- targets: ['127.0.0.1']labels:region: 'cn-north'metrics:- name: region_cpu_thresholdvalue: 85 -
向量匹配注意事项
- group_left/group_right必选:当两个向量的标签基数不匹配时,必须指定group_left或group_right,否则会报错;
- 标签保留:运算后保留“多”侧的标签,“一”侧的非匹配标签会被过滤;
- 运算优先级:向量运算优先级高于聚合运算,建议通过括号控制运算顺序。
五、语法速查表
5.1. 聚合分组语法:by vs without
| 语法 | 核心作用 | 语法格式 | 适用场景 |
|---|---|---|---|
| by | 仅保留指定标签为分组依据,结果含指定标签 | 聚合函数 (即时向量) by (标签 1,…) | 明确需保留的分组标签(如服务、实例) |
| without | 删除指定标签,剩余标签为分组依据 | 聚合函数 (即时向量) without (标签 1,…) | 排除少数无关标签(如排除 job 标签) |
5.2. 向量匹配调整语法:on vs ignoring
| 语法 | 核心作用 | 语法格式 | 适用场景 |
|---|---|---|---|
| on | 仅用指定标签匹配,忽略其他标签 | 向量 A 运算符号 on (标签 1,…) 向量 B | 两向量标签多,仅需部分标签匹配(如 instance) |
| ignoring | 忽略指定标签,用剩余标签匹配 | 向量 A 运算符号 ignoring (标签 1,…) 向量 B | 两向量仅少数标签不一致(如排除 code 标签) |
5.3. 多对一匹配语法:group_left vs group_right
| 语法 | 核心作用 | 语法格式 | 适用场景 |
|---|---|---|---|
| group_left | 左侧为 “多”、右侧为 “一”,一右配多左 | 向量 A (多) 运算符号 on/ignoring (标签) group_left 向量 B (一) | 多序列关联单序列数据(如各状态码关联总请求) |
| group_right | 右侧为 “多”、左侧为 “一”,一左配多右 | 向量 A (一) 运算符号 on/ignoring (标签) group_right 向量 B (多) | 多序列关联单序列阈值(如多实例关联区域阈值) |
关键说明
- 优先级:
on/ignoring与group_left/group_right配合使用,控制向量匹配;by/without仅作用于聚合函数。 - 标签保留:聚合后标签由
by/without控制;向量运算后保留 “多” 侧标签。
六、指标查询示例速查
-
服务器监控场景
-
CPU使用率
-
场景:计算各实例5分钟内非空闲CPU使用率,按实例分组。
-
逻辑:irate()计算瞬时空闲速率 → 按实例求平均 → 100减空闲率得到使用率。
100 - avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100
-
-
内存使用率
-
场景:计算各实例内存使用率,包含缓冲(Buffers)和缓存(Cached)的空闲内存。
-
说明:Linux系统中,Buffers和Cached可被回收,需计入“可用内存”。
(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100
-
-
磁盘使用率与预测
# 1. 计算/分区的磁盘使用率 (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) / node_filesystem_size_bytes{mountpoint="/"} * 100# 2. 基于1小时历史数据,预测4小时后/分区是否会耗尽空间(返回<0表示将耗尽) predict_linear(node_filesystem_free_bytes{mountpoint="/"}[1h], 4*3600) < 0
-
-
应用监控场景
-
HTTP接口核心指标
# 接口QPS: sum(rate(http_requests_total[5m])) by (path)# 接口错误率 sum(rate(http_requests_total{status_code=~"5.."}[5m])) by (path) / sum(rate(http_requests_total[5m])) by (path) * 100# 95分位响应时间: quantile(0.95, http_request_duration_seconds_sum / http_request_duration_seconds_count) by (path) -
服务健康状态
# 1. 监控systemd管理的node_exporter服务是否处于active状态(返回1正常,0异常) # 配置要求:node_exporter需启用--collector.systemd参数,并指定监控的服务单元。 node_systemd_unit_state{name="node_exporter.service", state="active"}
-
-
业务监控场景
# 1. 统计电商平台各支付方式的成功率(支付成功数/支付总次数),按支付方式(pay_type)分组。 # 说明:需业务代码埋点输出pay_success_total(支付成功计数器)和pay_total(支付总计数器)指标。 sum(rate(pay_success_total[5m])) by (pay_type) / sum(rate(pay_total[5m])) by (pay_type) * 100
