4. Metric 设计基础:Counter、Gauge、Histogram、Summary 的选择与适用场景

在可观测性体系中,Metric 是量化系统状态与行为的核心手段。选错 Metric 类型会导致误判、告警风暴或 MTTR 复盘失真。本章深入剖析 Prometheus 体系下四种核心 Metric 类型——Counter、Gauge、Histogram、Summary——的设计意图、适用场景与 SRE 实战陷阱。

4.1 四种 Metric 类型核心对比

类型 语义 典型值 可加减 适用场景
Counter 只增不减的累计值 请求总数、错误总数 只能加 吞吐量、错误计数、事件次数
Gauge 可增可减的瞬时值 CPU 使用率、内存用量 可加可减 资源水位、队列深度、连接数
Histogram 分桶统计分布 请求延迟分布、响应大小分布 分桶计数 延迟/尺寸的百分位估算、SLO 合规
Summary 预计算分位数 p50/p90/p99 延迟 客户端计算 已知分位数、低数据量、精确百分位
SRE 黄金法则:Counter 用于“发生了多少次”,Gauge 用于“当前是多少”,Histogram/Summary 用于“分布长什么样”。混淆 Counter 与 Gauge 是 MTTR 复盘数据失真的首要原因。

4.2 Counter:只增不减的累计器

Counter 代表一个单调递增的计数器,重启时归零。SRE 最常犯的错误是直接对 Counter 原始值做告警,而非使用 rate() 或 increase() 计算速率。

# 错误:对 Counter 原始值设置阈值
http_requests_total > 1000  # 重启后必然触发

# 正确:使用速率
rate(http_requests_total[5m]) > 100  # 每秒请求数

Counter 适用清单:

  • HTTP 请求总数、RPC 调用次数
  • 错误/异常发生次数
  • 任务执行次数、消息消费次数
  • 写入/读取字节数累计
陷阱:不要用 Counter 表示“当前在线人数”或“当前队列长度”——这些值会下降,应使用 Gauge。Counter 下降意味着重置或溢出,会破坏 rate() 计算。

4.3 Gauge:瞬时快照

Gauge 反映系统在采样时刻的瞬时状态,可升可降。Gauge 的告警逻辑通常基于原始值或变化率。

# 直接对 Gauge 原始值告警
node_memory_MemAvailable_bytes < 1e9  # 可用内存低于 1GB

# 对 Gauge 变化率告警(突增/突降)
deriv(node_memory_MemAvailable_bytes[5m]) < -5e7  # 内存下降速率过快

Gauge 适用清单:

  • CPU/内存/磁盘使用率
  • 当前活跃连接数、goroutine 数
  • 队列当前深度、缓冲池水位
  • 温度、风扇转速、电压
  • 业务指标:当前在线用户、库存量

4.4 Histogram:分布估算

Histogram 将观测值放入预定义桶(bucket),通过桶计数估算百分位数。适合延迟、响应大小等需要了解分布特征的场景。

# 定义 Histogram 桶(单位:秒)
http_request_duration_seconds_bucket{le="0.1"} 1200
http_request_duration_seconds_bucket{le="0.5"} 3400
http_request_duration_seconds_bucket{le="1.0"} 4100
http_request_duration_seconds_bucket{le="+Inf"} 4500

# 估算 p99
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

Histogram 设计要点:

  • 桶边界需覆盖业务 SLO 范围(如 SLO 为 200ms,则在 200ms 附近加密桶)
  • 桶数量建议 10-15 个,过多增加存储开销
  • +Inf 桶必须存在,用于兜底
  • Histogram 在服务端计算分位数,适合多实例聚合
MTTR 复盘价值:Histogram 能揭示“慢请求是否集中在特定时间段或实例”,帮助定位故障根因。例如 p99 突增但 p50 正常,说明尾部延迟恶化,可能指向某台慢实例。

4.5 Summary:预计算分位数

Summary 在客户端直接计算分位数并暴露结果,适合对精度要求高、数据量可控的场景。

# Summary 暴露的分位数(客户端预计算)
rpc_duration_seconds{quantile="0.5"} 0.052
rpc_duration_seconds{quantile="0.9"} 0.098
rpc_duration_seconds{quantile="0.99"} 0.152

Summary 与 Histogram 对比:

维度 Histogram Summary
分位数计算位置 服务端(PromQL) 客户端(应用内)
聚合能力 支持多实例聚合 不支持聚合(相加无意义)
精度控制 依赖桶边界设计 可指定误差范围
存储开销 桶数 × 标签基数 分位数数量 × 标签基数
适用场景 多实例聚合、SLO 监控 单实例精确分位数、低基数
陷阱:Summary 的分位数无法在 PromQL 中跨实例求和。如果需要对多个实例的 p99 取全局 p99,必须使用 Histogram。Summary 适合“每个实例独立看分位数”的场景。

4.6 选择决策流程

以下 SVG 流程图帮助 SRE 工程师快速选择正确的 Metric 类型:

Metric 类型选择决策流程 观测值类型? 只增不减?→ Counter 可增可减?→ Gauge 分布特征?→ 继续 需要聚合? 是 → Histogram 否 → Summary 决策要点 • 累计事件次数 → Counter • 瞬时水位/状态 → Gauge • 需要跨实例聚合分位数 → Histogram • 单实例精确分位数 → Summary

4.7 实战案例:MTTR 复盘中的 Metric 选择

某电商系统在双十一期间出现支付接口延迟飙升,SRE 团队复盘时发现以下 Metric 设计问题:

原始设计 问题 优化方案
payment_latency_ms (Gauge) Gauge 无法反映延迟分布,仅记录瞬时值,无法计算 p99 改为 Histogram,桶边界设为 [50, 100, 200, 500, 1000, 2000, 5000]
payment_errors_total (Counter) 直接对原始值告警,重启后误报 使用 rate(payment_errors_total[5m]) 计算错误率
active_connections (Counter) 连接数会下降,Counter 语义错误 改为 Gauge,正确反映当前连接数
复盘结论:错误的 Metric 类型选择导致 MTTR 复盘时无法准确识别“延迟分布恶化”这一根因。优化后,通过 Histogram 的 p99 突增定位到某台数据库实例的慢查询,MTTR 从 45 分钟降至 12 分钟。

4.8 最佳实践清单

  • Counter 必配 rate():所有 Counter 告警和图表都应使用 rate() 或 increase(),避免重启干扰
  • Gauge 关注变化率:除原始值告警外,增加 deriv() 或 delta() 检测突增/突降
  • Histogram 桶对齐 SLO:桶边界应覆盖 SLO 目标值,并在目标值附近加密
  • Summary 慎用聚合:明确 Summary 不可跨实例求和,多实例场景优先选 Histogram
  • 标签基数控制:无论哪种类型,标签基数建议控制在 1000 以内,避免高基数爆炸
  • 统一命名规范:类型后缀(_total、_bucket、_count、_sum)必须遵循 Prometheus 命名约定
SRE 检查清单:每次新增 Metric 前,问自己三个问题——(1) 这个值会下降吗?(2) 我需要分布还是均值?(3) 需要跨实例聚合吗?答案直接决定 Metric 类型。