2. Metric 数据类型详解:定义与适用场景
在可观测性工程中,选择正确的 Metric 数据类型是构建精准告警阈值的基础。Prometheus 定义了四种核心 Metric 类型:Counter、Gauge、Histogram 和 Summary。每种类型对应不同的数据特征与查询模式,错误的选择会导致告警失真或性能浪费。
核心原则: 数据类型决定了指标的可聚合性、统计语义以及告警表达式的写法。在定义 SLO 和告警规则前,必须为每个观测指标匹配正确的数据类型。
2.1 Counter(计数器)
定义: Counter 是一种只增不减的累计值,仅在系统重启或重置时归零。它用于记录事件发生的次数或累计量。
核心特征:
- 单调递增: 值只能增加或归零(重启),不能减少。
- 原子操作: 适合高并发场景下的计数。
- 衍生计算: 原始值本身意义有限,通常通过
rate()、increase()函数计算变化率。
适用场景:
| 场景 | 示例 Metric | 告警表达式 |
|---|---|---|
| HTTP 请求总数 | http_requests_total |
rate(http_requests_total[5m]) > 1000 |
| 错误次数 | errors_total |
rate(errors_total[5m]) > 10 |
| 任务执行次数 | job_executions_total |
increase(job_executions_total[1h]) == 0 |
| 网络字节流入量 | network_bytes_received_total |
rate(network_bytes_received_total[1m]) > 1e9 |
避坑提示: 不要用 Counter 直接设置阈值告警(如
errors_total > 100),因为累计值会随时间无限增长,导致告警永远触发。必须使用 rate() 或 increase() 转换为速率。
2.2 Gauge(仪表盘)
定义: Gauge 表示一个可上下波动的瞬时值,反映系统的当前状态。它是最直观的指标类型。
核心特征:
- 可增可减: 值可以任意变化,没有单调性约束。
- 快照语义: 直接反映采样时刻的数值,无需速率转换。
- 适合阈值告警: 原始值可直接用于比较。
适用场景:
| 场景 | 示例 Metric | 告警表达式 |
|---|---|---|
| CPU 使用率 | cpu_usage_percent |
cpu_usage_percent > 90 |
| 内存使用量 | memory_used_bytes |
memory_used_bytes > 8e9 |
| 队列深度 | queue_depth |
queue_depth > 1000 |
| 连接数 | active_connections |
active_connections > 5000 |
最佳实践: Gauge 适合与
avg_over_time()、max_over_time() 等聚合函数配合,消除瞬时抖动,生成更稳定的告警阈值。
2.3 Histogram(直方图)
定义: Histogram 将观测值(如请求延迟)分配到预定义的桶(bucket)中,同时记录所有观测值的总和与总数。它用于分析数据的分布特征。
核心特征:
- 分桶统计: 每个桶记录落在该区间内的观测次数。
- 可计算分位数: 通过
histogram_quantile()函数估算 P50、P90、P99 等。 - 可聚合: 多个 Histogram 可以合并计算全局分位数。
适用场景:
| 场景 | 示例 Metric | 告警表达式 |
|---|---|---|
| 请求延迟分布 | http_request_duration_seconds |
histogram_quantile(0.99, rate(...)) > 0.5 |
| 响应大小分布 | http_response_size_bytes |
histogram_quantile(0.95, rate(...)) > 1e6 |
| 数据库查询耗时 | db_query_duration_seconds |
histogram_quantile(0.9, rate(...)) > 2 |
告警优势: Histogram 能发现“大多数请求正常,但少数请求极慢”的尾部延迟问题,这是平均值告警无法捕获的。
2.4 Summary(摘要)
定义: Summary 在客户端直接计算分位数,并将结果暴露为预定义的分位数(如 P50、P90、P99)以及观测总数和总和。
核心特征:
- 客户端计算: 分位数在应用端算好,服务端直接读取。
- 固定分位数: 分位数在定义时指定,无法动态查询其他分位。
- 不可聚合: 多个 Summary 的分位数不能合并计算全局分位。
适用场景:
| 场景 | 示例 Metric | 告警表达式 |
|---|---|---|
| 已知分位数的延迟监控 | rpc_duration_seconds |
rpc_duration_seconds{quantile="0.99"} > 1 |
| 预计算性能指标 | api_latency_milliseconds |
api_latency_milliseconds{quantile="0.95"} > 200 |
关键限制: Summary 的分位数无法跨实例聚合。如果你需要全局 P99,必须使用 Histogram。Summary 更适合单实例的精确分位需求。
2.5 四种类型对比总览
| 特性 | Counter | Gauge | Histogram | Summary |
|---|---|---|---|---|
| 值变化方向 | 只增不减 | 可增可减 | 累计计数 | 累计计数 |
| 原始值可用性 | 低(需 rate) | 高(直接使用) | 中(需分桶计算) | 中(直接读分位) |
| 分位数支持 | 不支持 | 不支持 | 支持(服务端计算) | 支持(客户端计算) |
| 跨实例聚合 | 支持 | 支持 | 支持 | 不支持 |
| 典型告警方式 | 速率阈值 | 值阈值 | 分位数阈值 | 分位数阈值 |
| 存储开销 | 低 | 低 | 高(桶数相关) | 中 |
2.6 数据类型选择决策流程
2.7 告警阈值设计中的类型选择建议
- 速率类告警(如 QPS 突增): 使用 Counter +
rate(),设置每秒或每分钟的速率阈值。 - 饱和度类告警(如 CPU 高): 使用 Gauge,设置百分比或值的上下限。
- 尾部延迟告警(如 P99 超时): 使用 Histogram,通过
histogram_quantile()设置分位数阈值。 - 预知分位需求(如固定 P95 监控): 使用 Summary,但注意无法聚合多实例。
实战建议: 在微服务架构中,推荐统一使用 Histogram 记录延迟,以便在全局维度聚合计算 SLO。仅在明确不需要跨实例聚合且对性能有极致要求时,才考虑 Summary。