3. PromQL 聚合操作:sum、avg、min、max、count、topk、quantile 等聚合函数详解

在 PromQL 中,聚合操作是将一组时间序列合并为单一序列的核心手段。当您面对成百上千个实例(如所有 Web 服务器的 CPU 使用率)时,聚合函数能将原始数据转化为可决策的黄金指标(如“集群平均 CPU 使用率”或“P99 延迟”)。

3.1 聚合操作基础语法

所有聚合函数遵循统一语法结构:

<聚合函数>([参数,] <PromQL 表达式>) [without|by (<标签列表>)]
  • 聚合函数:sum、avg、min、max、count、topk、quantile 等。
  • 参数:仅 topk、quantile 等需要额外数值参数。
  • without / by:控制保留或移除哪些标签维度。
💡 关键区别:
by (instance) 表示“按 instance 分组聚合”,结果中保留 instance 标签;
without (instance) 表示“聚合时排除 instance 标签”,结果中不包含 instance。

3.2 核心聚合函数速查表

函数 作用 典型场景 示例
sum 求和 总请求量、总内存使用 sum(http_requests_total)
avg 平均值 平均延迟、平均 CPU 使用率 avg(node_cpu_seconds_total)
min 最小值 最空闲节点、最低延迟 min(node_memory_MemFree_bytes)
max 最大值 最繁忙节点、最高延迟 max(http_request_duration_seconds)
count 计数 在线实例数、满足条件的节点数 count(up == 1)
topk 取前 K 个最大值 Top 5 最慢接口、Top 3 最耗 CPU 容器 topk(5, http_request_duration_seconds)
quantile 分位数(0~1) P50、P90、P99 延迟 quantile(0.99, http_request_duration_seconds)

3.3 聚合函数详解与实战

3.3.1 sum —— 最常用的求和

sum 将多个时间序列的样本值相加。常用于计算总量指标:

# 所有实例的总请求数
sum(http_requests_total)

# 按状态码分组的总请求数
sum by (status_code) (http_requests_total)

3.3.2 avg —— 消除实例差异

avg 计算平均值,适合评估整体健康度:

# 集群平均 CPU 使用率
avg(rate(node_cpu_seconds_total{mode="idle"}[5m]))

3.3.3 min / max —— 边界检测

min 和 max 用于发现异常极端值:

# 找出延迟最高的服务
max(http_request_duration_seconds)

# 找出剩余内存最少的节点
min(node_memory_MemFree_bytes)

3.3.4 count —— 实例计数

count 统计序列数量,常用于可用性监控:

# 当前健康的实例数
count(up == 1)

# 按 region 统计在线实例
count by (region) (up == 1)

3.3.5 topk —— 聚焦头部异常

topk(k, expr) 返回数值最大的 K 个序列,保留原始标签:

# 延迟最高的 5 个端点
topk(5, http_request_duration_seconds)
⚠️ 注意:topk 和 bottomk 返回的是原始序列(带标签),不是聚合后的单条线。在图表中会显示多条线。

3.3.6 quantile —— 延迟分布黄金函数

quantile(φ, expr) 计算 φ 分位数(0 ≤ φ ≤ 1)。这是 SRE 黄金指标中延迟分布的核心:

# P99 延迟(99% 的请求在此值以下)
quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

# 同时计算 P50、P90、P99
quantile(0.50, rate(http_request_duration_seconds_bucket[5m]))
quantile(0.90, rate(http_request_duration_seconds_bucket[5m]))
quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

3.4 聚合操作流程与标签控制

下图展示了从原始时间序列到聚合结果的完整流程,以及 by 与 without 对标签维度的不同影响:

聚合操作流程:by vs without 标签控制 原始时间序列 instance="web-1", status="200" instance="web-2", status="200" instance="web-1", status="500" 聚合函数 sum / avg / count topk / quantile by (status) 保留 status 标签 结果:status="200" → 2 结果:status="500" → 1 without (instance) 移除 instance 标签 结果:仅保留 status 聚合所有实例 📌 标签控制规则 • by (label):只保留指定标签,其他标签被聚合消除 • without (label):移除指定标签,保留其余所有标签 • 不写 by/without 时,默认聚合所有标签,生成单条序列

3.5 聚合操作实战对比表

场景 推荐函数 示例表达式 输出说明
集群总 QPS sum sum(rate(http_requests_total[1m])) 所有实例请求速率之和
平均响应时间 avg avg(rate(http_request_duration_seconds_sum[1m]) / rate(http_request_duration_seconds_count[1m])) 所有实例的平均延迟
最慢接口 Top 5 topk topk(5, avg by (handler) (rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m]))) 返回 5 个最慢 handler
P99 延迟 quantile quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) 99% 请求在此值以下
在线实例数 count count(up == 1) 健康实例总数
最大内存使用 max max(container_memory_usage_bytes) 最耗内存的容器

3.6 常见陷阱与最佳实践

✅ 最佳实践:
  • 先 rate 再聚合:对 Counter 类型指标,先 rate() 或 increase() 再聚合,避免因重启导致数据失真。
  • 明确标签维度:使用 by 保留关键维度(如 job、service),避免过度聚合丢失排查线索。
  • quantile 配合 histogram:分位数计算必须基于 _bucket 指标,直接对 Gauge 使用 quantile 无意义。
⚠️ 常见陷阱:
  • sum 后丢失实例维度:sum(up) 只告诉你总数,无法知道哪个实例挂了。建议配合 by (instance) 或保留告警标签。
  • topk 在 dashboard 中闪烁:由于 topk 每次只取前 K,当数据波动时,图表中的序列会频繁切换,建议结合 avg_over_time 平滑。
  • count 与 count_values 混淆:count 统计序列数量;count_values 统计每个样本值出现的次数,二者完全不同。

3.7 聚合函数选择决策流程

当您面对一个监控需求时,可按以下流程快速选择正确的聚合函数:

聚合函数选择决策树 需要什么信息? 总量 / 总速率 平均值 / 健康度 分布 / 极端值 sum count avg quantile topk 📌 决策提示 • 需要“最”值(最大/最小)→ 直接使用 max / min • 需要“前 N”个异常 → topk / bottomk • 需要“百分之多少”的分布 → quantile(配合 histogram)

3.8 录制规则中的聚合应用

在录制规则(Recording Rules)中,聚合函数常用于预计算高频使用的黄金指标,降低查询延迟:

# 示例:预计算集群 P99 延迟(每 30 秒更新)
groups:
  - name: latency_aggregates
    interval: 30s
    rules:
      - record: cluster:http_request_duration_seconds:p99
        expr: quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

      - record: cluster:http_requests_total:rate5m
        expr: sum(rate(http_requests_total[5m]))

      - record: instance:node_cpu_usage:avg
        expr: avg by (instance) (rate(node_cpu_seconds_total{mode!="idle"}[5m]))
🎯 录制规则命名规范:
<level>:<metric_name>:<operation>
例如 cluster:http_requests_total:rate5m 表示“集群级别、5 分钟速率聚合”。