4. 聚合操作符实战:sum、avg、min、max、count、stddev、topk、quantile_over_time
聚合操作符是 PromQL 从原始时间序列数据中提取业务语义的核心工具。在告警规则编写中,聚合操作符决定了“谁触发告警”以及“告警的严重程度如何计算”。本章将逐一拆解 8 个最常用的聚合操作符,并结合收敛场景给出工程化建议。
4.1 聚合操作符分类与适用场景
聚合操作符按计算维度可分为三类:集合型(sum、count)、统计型(avg、min、max、stddev)、排序型(topk、quantile_over_time)。下表列出了各操作符的核心用途与典型告警场景:
| 操作符 | 类型 | 核心用途 | 典型告警场景 |
|---|---|---|---|
sum |
集合型 | 对维度值求和,常用于总量统计 | 总请求量、总错误数、总 CPU 使用率 |
avg |
统计型 | 计算平均值,消除毛刺 | 平均延迟、平均负载、平均错误率 |
min |
统计型 | 取最小值,关注最差情况 | 最低可用副本数、最小磁盘剩余空间 |
max |
统计型 | 取最大值,关注峰值 | 最大延迟、最高 CPU 使用率 |
count |
集合型 | 统计非空序列数量 | 存活实例数、异常指标数 |
stddev |
统计型 | 计算标准差,衡量波动 | 延迟抖动、负载不均衡度 |
topk |
排序型 | 返回 Top K 序列 | 最高延迟的 5 个实例、错误最多的 3 个服务 |
quantile_over_time |
排序型 | 在时间窗口内计算分位数 | P99 延迟、P95 错误率 |
工程建议:在告警表达式中,优先使用
avg 或 quantile_over_time 代替 sum 做阈值判断,因为总量容易受实例数变化影响,导致误告警。
4.2 集合型操作符:sum、count
sum 是最常用的聚合操作符,用于将多个时间序列的值相加。在告警中,sum 通常配合 by 子句保留关键维度,避免过度聚合丢失上下文。
# 按 service 维度聚合总请求量
sum by (service) (rate(http_requests_total[5m]))
# 按 region 维度聚合总错误数
sum by (region) (rate(http_errors_total[5m]))
count 用于统计满足条件的序列数量,常用于检测实例数是否低于预期:
# 统计当前存活的实例数
count by (service) (up == 1)
# 统计延迟超过 500ms 的实例数
count by (service) (http_request_duration_seconds > 0.5)
避坑提示:
count 统计的是时间序列数量,不是数值总和。如果指标带有多个标签(如 instance、method、path),count 结果可能远大于实际实例数,务必使用 by 子句缩小维度。
4.3 统计型操作符:avg、min、max、stddev
统计型操作符用于描述数据分布的中心趋势和离散程度。在告警收敛中,avg 和 max 的组合使用最为常见:
# 平均 CPU 使用率超过 80% 告警
avg by (host) (rate(cpu_usage_percent[5m])) > 80
# 任意实例 CPU 使用率超过 95% 告警(关注峰值)
max by (host) (rate(cpu_usage_percent[5m])) > 95
stddev 用于检测负载不均衡或异常波动:
# 各实例延迟标准差超过 200ms 时告警
stddev by (service) (http_request_duration_seconds) > 0.2
收敛策略:当
stddev 突然增大但 avg 变化不大时,说明部分实例出现异常,此时应触发“负载不均衡”告警,而非直接对平均值告警。
4.4 排序型操作符:topk、quantile_over_time
topk 用于返回数值最大的 K 个序列,适合在告警中定位“最差”的实例:
# 返回延迟最高的 5 个实例
topk(5, http_request_duration_seconds)
# 在告警规则中,topk 通常配合其他操作符使用
# 例如:对 topk 的实例单独告警
topk(3, max by (instance) (rate(http_errors_total[5m]))) > 10
quantile_over_time 是 聚合函数(非操作符),用于在时间窗口内计算分位数。它是构建 P99/P95 告警的核心工具:
# 计算过去 5 分钟的 P99 延迟
quantile_over_time(0.99, http_request_duration_seconds[5m])
# 在告警规则中使用
quantile_over_time(0.99, http_request_duration_seconds[5m]) > 1.0
性能注意:
quantile_over_time 需要在内存中保留完整的时间窗口数据,窗口越大内存开销越高。建议生产环境窗口不超过 10 分钟,并配合 record 规则预计算。
4.5 聚合操作符与收敛规则组合
在告警收敛中,聚合操作符的嵌套使用可以显著减少告警风暴。下图展示了从原始指标到收敛告警的典型流程:
4.6 聚合操作符选择矩阵
在实际告警规则编写中,选择合适的聚合操作符需要综合考虑指标类型、告警目标和收敛效果。下表给出了不同场景下的推荐选择:
| 告警目标 | 推荐操作符 | 收敛配合 | 示例表达式 |
|---|---|---|---|
| 检测服务整体健康度 | avg |
for: 3m |
avg by (service) (up) < 0.8 |
| 检测单实例异常 | max / topk |
for: 1m |
max by (instance) (error_rate) > 5 |
| 检测负载不均衡 | stddev |
for: 5m |
stddev by (service) (cpu_usage) > 20 |
| 检测延迟毛刺 | quantile_over_time |
record 预计算 |
quantile_over_time(0.99, latency[5m]) > 1.0 |
| 检测实例数不足 | count |
for: 2m |
count by (service) (up) < 3 |
4.7 实战:编写一个多维度聚合告警规则
以下是一个完整的告警规则示例,综合使用了 sum、avg、quantile_over_time 和收敛参数:
groups:
- name: api_latency_alerts
rules:
# 规则1:P99 延迟超过 2s 告警(预计算)
- record: job:api:p99_latency:5m
expr: quantile_over_time(0.99, api_request_duration_seconds[5m])
- alert: HighP99Latency
expr: job:api:p99_latency:5m > 2.0
for: 2m
labels:
severity: critical
annotations:
summary: "API P99 latency high ({{ $value }}s)"
# 规则2:平均延迟超过 1s 告警(聚合收敛)
- alert: HighAvgLatency
expr: avg by (service) (rate(api_request_duration_seconds_sum[5m]) / rate(api_request_duration_seconds_count[5m])) > 1.0
for: 3m
labels:
severity: warning
annotations:
summary: "Service {{ $labels.service }} avg latency high"
# 规则3:单实例延迟异常(topk 定位)
- alert: InstanceLatencySpike
expr: topk(3, max by (instance) (api_request_duration_seconds)) > 3.0
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} latency spike"
关键点:
- 使用
record规则预计算quantile_over_time,避免每次告警评估都重新计算。 - 不同严重级别使用不同的
for时长:critical 用 2m,warning 用 3m,减少误告警。 topk只返回 Top 3 实例,避免告警风暴。
4.8 常见错误与排查方法
聚合操作符使用不当是告警误报和漏报的主要原因。下表列出了 5 个常见错误及对应的排查方法:
| 错误现象 | 可能原因 | 排查方法 |
|---|---|---|
| 告警值远高于预期 | sum 未使用 by 子句,聚合了所有维度 |
在 Prometheus UI 中执行 sum(metric) 查看原始值 |
| 告警频繁触发/解除 | 使用了 min 或 max 但未加 for 收敛 |
增加 for: 2m 或改用 avg |
| P99 告警不准确 | quantile_over_time 窗口过短 |
将窗口从 1m 调整为 5m 或 10m |
| topk 告警无输出 | topk 返回的是序列,不是标量 |
配合 max 或 avg 转换为标量再比较 |
| stddev 告警无意义 | 指标本身波动大,stddev 天然高 | 改用 stddev / avg 计算变异系数 |
核心原则:聚合操作符的选择直接影响告警的准确性和收敛效果。在编写告警规则前,务必在 Prometheus UI 中先用
sum、avg、topk 等操作符预览数据分布,确认聚合后的数值符合预期后再写入规则文件。