Skip to content
Prometheus 核心概念

Prometheus 核心概念

本文档涵盖 Prometheus 四种核心指标类型和 PromQL 查询语言。选择合适的指标类型和掌握 PromQL 对查询性能、存储效率和告警准确性至关重要。

符号说明

符号 含义
🚨 陷阱 / Pitfall
💡 最佳实践 / Best practice
🔬 深入原理 / Deep-dive
性能提示 / Performance note

1. 指标类型详解

Prometheus 提供四种核心指标类型。

1.1 Counter(计数器)

特点: 只增不减(除非进程重启导致重置为 0)。

适用场景: 请求总数、错误次数、完成任务数、累计字节数。

# HELP http_requests_total Total HTTP requests
# TYPE http_requests_total counter
http_requests_total{method="GET", status="200"} 1048576
http_requests_total{method="POST", status="201"} 524288
关键操作 说明
Inc() / Add(n) 增加计数
⛔ 不可 Dec() Counter 不可减少

🔬 深入原理: Counter 存储的是累计值,直接使用这个值没有意义。必须用 rate()increase() 转换成每秒速率时间窗口内增量rate() 能自动处理计数器重置(比如进程重启时归零)。

1.2 Gauge(仪表盘)

特点: 可增可减,反映当前瞬时状态。

适用场景: CPU 使用率、内存占用、活跃连接数、队列深度、温度。

# HELP node_memory_MemAvailable_bytes Available memory
# TYPE node_memory_MemAvailable_bytes gauge
node_memory_MemAvailable_bytes 8589934592
关键操作 说明
Set(v) 设为指定值
Inc() / Dec() +1 / -1
Add(n) / Sub(n) 批量加减

💡 Gauge 可直接查询当前值,不需要套 rate()。但对 Gauge 做趋势分析时,用 delta()deriv()predict_linear()

1.3 Histogram(直方图)

特点: 将观测值落入预定义的桶(bucket)中计数,自动生成 _bucket_sum_count 三个子指标。

适用场景: 请求延迟分布、响应体大小分布——任何需要跨实例聚合后计算分位数的场景。

# HELP http_request_duration_seconds HTTP request duration
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.005"} 0
http_request_duration_seconds_bucket{le="0.01"} 15
http_request_duration_seconds_bucket{le="0.025"} 55
http_request_duration_seconds_bucket{le="0.05"} 143
http_request_duration_seconds_bucket{le="0.1"} 321
http_request_duration_seconds_bucket{le="0.25"} 567
http_request_duration_seconds_bucket{le="0.5"} 712
http_request_duration_seconds_bucket{le="1.0"} 843
http_request_duration_seconds_bucket{le="+Inf"} 1000
http_request_duration_seconds_sum 245.6
http_request_duration_seconds_count 1000

🔬 深入原理: Histogram 的核心价值在于 可聚合。多个实例的 _bucket 可以用 sum() 合并,再用 histogram_quantile() 算出全局分位数。这是 Summary 做不到的。

💡 桶的边界应对齐 SLO 阈值。 比如 SLO 是 P99 < 500ms,就该在 100ms、250ms、500ms、1s 处设桶。

1.4 Summary(摘要)

特点:客户端直接计算分位数(φ-quantile),暴露 _sum_count 和带 quantile 标签的分位数值。

适用场景: 单实例的精确分位数(不需要跨实例聚合时)。

# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 1.23e-05
go_gc_duration_seconds{quantile="0.5"} 0.000123
go_gc_duration_seconds{quantile="0.9"} 0.000456
go_gc_duration_seconds{quantile="0.99"} 0.001234
go_gc_duration_seconds_sum 52.3
go_gc_duration_seconds_count 10000

1.5 四种类型对比与选择

维度 Counter Gauge Histogram Summary
方向 只增不减 可增可减 Bucket 是 Counter 分位数是 Gauge
典型场景 请求计数 当前温度 延迟分布 客户端精确分位
跨实例聚合 sum(rate()) avg() histogram_quantile(sum()) ❌ 不可聚合
查询分位数 ✅ 服务端计算 ✅ 客户端计算
CPU 开销 极低 极低 较高(客户端排序)
推荐度 必用 必用 ⭐ 首选 仅限单机场景

🚨 Summary 的分位数不可聚合! 50 台机器的 P99 平均值 ≠ 全局 P99。需要全局分位数时请用 Histogram。


2. PromQL 查询语言

PromQL 是 Prometheus 的函数式查询语言,所有仪表盘、告警规则都依赖它。

2.1 数据类型

类型 说明 示例
Instant Vector(瞬时向量) 一组时间序列,每个只有一个时间点的值 http_requests_total
Range Vector(区间向量) 一组时间序列,每个有一段时间范围内的值 http_requests_total[5m]
Scalar(标量) 单个浮点数 3.14
String(字符串) 字符串值(极少使用) "hello"

2.2 选择器与标签匹配

# 精确匹配
http_requests_total{method="GET", status="200"}

# 否定匹配
http_requests_total{method!="GET"}

# 正则匹配
http_requests_total{method=~"GET|POST"}

# 否定正则
http_requests_total{method!~"DELETE|PATCH"}

# 多个条件(AND 关系)
{job=~"node.*", instance=~"10\\.1\\.150\\..*"}

💡 正则匹配牢记:=~ 是匹配,!~ 是不匹配。

2.3 Counter 专属:rate() / irate() / increase()

🚨 黄金法则:永远不要直接对 Counter 原始值做查询或告警——进程中累计 3 天跑了 1 亿次请求,原始值没有任何意义。必须用 rate()increase() 转换。

# === rate() — 每秒平均增长率(推荐用于仪表盘和告警)===
rate(http_requests_total[5m])

# === irate() — 瞬时增长率(仅最后两个样本点计算,灵敏度极高)===
irate(http_requests_total[5m])

# === increase() — 时间窗口内总增长量 ===
increase(http_requests_total[1h])
特性 rate() irate() increase()
计算方式 窗口内所有点的平均斜率 仅最后两个点 rate × 窗口秒数
灵敏度 中等 极高 中等
曲线平滑度 低(嘈杂)
适用于告警 ⚠️(可用但不如 rate 直观)
适用于图表
适用于突发检测 ⚠️ ⚠️

💡 时间窗口 ≥ 4× scrape_interval。 比如 scrape_interval=30s,则 [5m] 是合理的最小窗口;用 [2m][1m] 会产生抖动。

🔬 深入原理: rate()increase() 都采用外推(extrapolation),把数据点布局到窗口的全长。所以 increase() 的结果可能是非整数(如 123.45 个请求),即使原始数据都是整数。这是预期行为。

常用组合:

# 每秒请求数(按状态码分)
sum(rate(http_requests_total[5m])) by (status_code)

# 错误率百分比
sum(rate(http_requests_total{status=~"5.."}[5m]))
  / (sum(rate(http_requests_total[5m])) > 0)
  * 100

# APDEX(Apdex 分数)
sum(rate(http_request_duration_seconds_bucket{le="0.5"}[5m]))
  / sum(rate(http_request_duration_seconds_count[5m]))

2.4 Gauge 专属:时间聚合函数

# 过去 10 分钟的平均内存
avg_over_time(memory_usage_bytes[10m])

# 过去 1 小时的 CPU 峰值
max_over_time(cpu_usage_percent[1h])

# 过去 1 小时的最小值
min_over_time(free_disk_bytes[1h])

# net change(后值减前值)
delta(queue_size[1h])

# 每秒斜率(线性回归)
deriv(temperature_celsius[1h])

# 预测未来值(线性回归外推)
predict_linear(free_disk_bytes[1h], 3600)  # 预测 1 小时后的值

🚨 delta()deriv() 不处理计数器重置。只用于 Gauge。对 Counter 用 delta() 会在重启时产生巨大的假负值。

2.5 Histogram 专属:histogram_quantile()

# P99 延迟(全聚合 —— 最常用的模式)
histogram_quantile(0.99,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (le))

# P50 / P95 / P99 同时查询
histogram_quantile(0.50, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))

# 按服务分组
histogram_quantile(0.99,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service))

# 平均延迟(不是分位数,但常用)
  rate(http_request_duration_seconds_sum[5m])
/ rate(http_request_duration_seconds_count[5m])

🚨 忘记 by (le) 必返回 NaN。 le 标签是 histogram_quantile() 计算分位数的核心,聚合时必须保留。

🚨 最高 bucket 不够大时返回 +Inf 确保有 le="+Inf" 的 bucket,且最大有限 bucket 覆盖到实际数据范围。

2.6 聚合运算符

# 按标签分组求和
sum(rate(http_requests_total[5m])) by (method, status)

# 排除指定标签后求和
sum without(cpu, mode)(rate(node_cpu_seconds_total[5m]))

# 其他聚合:avg, min, max, count, stddev, stdvar

# topk / bottomk — 取前/后 K 条序列
topk(5, rate(http_requests_total[5m]))

# quantile — 跨序列分位数(注意:不是 histogram_quantile!)
quantile(0.95, rate(http_requests_total[5m]))

2.7 运算符与向量匹配

# 算术运算
rate(http_requests_total[5m]) * 60           # 转成每分钟
1 - (node_memory_MemAvailable / node_memory_MemTotal)  # 内存使用率

# 比较运算
rate(errors_total[5m]) > 0.1                 # 错误率超过 0.1/s

# 布尔运算(and / or / unless)
rate(http_requests_total{status="500"}[5m])
  and
rate(http_requests_total{status="200"}[5m])  # 有 500 且也有 200

# on / ignoring — 指定匹配标签
rate(http_requests_total[5m]) * on(instance) group_left
  node_memory_MemAvailable_bytes

2.8 时间偏移

# 查看 1 小时前的数据
http_requests_total offset 1h

# 与前一日同时段对比
rate(http_requests_total[5m])
  /
rate(http_requests_total[5m] offset 1d)

2.9 函数速查表

函数 适用范围 返回 处理重置 告警推荐
rate() Counter 每秒速率
irate() Counter 瞬时速率
increase() Counter 总增量 ⚠️
resets() Counter 重置次数 N/A
delta() Gauge 差值 ⚠️
deriv() Gauge 斜率/秒 ⚠️
predict_linear() Gauge 预测值
avg_over_time() Gauge 窗口均值 ⚠️
max_over_time() Gauge 窗口最大值 ⚠️
histogram_quantile() Histogram 分位数 N/A
absent() 任意 是否无数据 N/A
absent_over_time() Range 窗口内是否无数据 N/A
changes() 任意 变化次数
sort() / sort_desc() 任意 排序
label_replace() 任意 重命名标签
label_join() 任意 合并标签
vector() Scalar 标量→向量

参考资料: