2. Prometheus 基础回顾:指标类型与数据模型
在深入降级熔断作业模板的性能调优之前,必须牢固掌握 Prometheus 的四种核心指标类型及其背后的数据模型。指标类型决定了数据的聚合方式与查询语义,而数据模型则定义了如何唯一标识一条时间序列。本节将系统梳理这两大基础,为后续的指标采集、告警规则编写与性能分析奠定坚实的理论基础。
2.1 四种核心指标类型
Prometheus 客户端库提供四种指标类型(Metric Types),每种类型对应不同的使用场景与聚合行为。下表从语义、典型用途与聚合方式三个维度进行对比:
| 指标类型 | 语义 | 典型用途 | 聚合方式 |
|---|---|---|---|
| Counter | 只增不减的累计值 | 请求总数、错误总数、CPU 时间 | rate() / increase() |
| Gauge | 可增可减的瞬时值 | 内存使用量、并发连接数、队列深度 | 直接取值 / avg() / max() |
| Histogram | 分桶统计的分布值 | 请求延迟、响应大小 | histogram_quantile() |
| Summary | 客户端预计算的 φ-分位数 | 延迟分位数(无法聚合时) | 直接读取分位数 |
2.2 Counter:只增不减的累计器
Counter 是最基础的指标类型,其值在进程生命周期内单调递增。重启后重置为 0。直接使用 Counter 的原始值没有意义,必须通过 rate() 或 increase() 函数计算每秒增长率或一段时间内的增量。
# 示例:统计降级请求总数
# HELP degraded_requests_total 降级请求总数
# TYPE degraded_requests_total counter
degraded_requests_total{service="order",degradation_type="timeout"} 1024
# 查询:过去 5 分钟降级请求的每秒增长率
rate(degraded_requests_total[5m])
avg() 或 sum() 聚合原始值,这会导致重启后的重置行为污染计算结果。始终使用 rate() 或 increase() 包裹。
2.3 Gauge:可增可减的瞬时表盘
Gauge 用于表示可上下波动的瞬时值,如内存使用量、当前活跃连接数、熔断器状态(0/1 表示关闭/开启)。Gauge 的原始值可以直接用于告警与展示。
# 示例:熔断器状态(1=开启,0=关闭)
# HELP circuit_breaker_state 熔断器状态
# TYPE circuit_breaker_state gauge
circuit_breaker_state{service="order",instance="10.0.1.5:8080"} 1
# 查询:当前所有熔断器开启的服务
circuit_breaker_state == 1
2.4 Histogram:分桶分布与分位数计算
Histogram 将观测值(如请求延迟)分配到预定义的桶(bucket)中,同时记录所有观测值的总和与计数。通过 histogram_quantile() 函数可以在服务端计算 φ-分位数(如 P99、P95)。
# 示例:降级请求延迟分布
# HELP degraded_request_duration_seconds 降级请求延迟(秒)
# TYPE degraded_request_duration_seconds histogram
degraded_request_duration_seconds_bucket{le="0.1"} 500
degraded_request_duration_seconds_bucket{le="0.5"} 800
degraded_request_duration_seconds_bucket{le="1.0"} 950
degraded_request_duration_seconds_bucket{le="+Inf"} 1000
degraded_request_duration_seconds_sum 320.5
degraded_request_duration_seconds_count 1000
# 查询:降级请求的 P99 延迟
histogram_quantile(0.99, rate(degraded_request_duration_seconds_bucket[5m]))
2.5 Summary:客户端预计算的分位数
Summary 与 Histogram 类似,但分位数在客户端预计算,直接暴露为 quantile 标签。Summary 无法在服务端跨实例聚合,因此适用于已知全局分位数不需要聚合的场景。
# 示例:Summary 格式的延迟分位数
# HELP rpc_duration_seconds RPC 延迟(秒)
# TYPE rpc_duration_seconds summary
rpc_duration_seconds{quantile="0.5"} 0.052
rpc_duration_seconds{quantile="0.9"} 0.120
rpc_duration_seconds{quantile="0.99"} 0.350
rpc_duration_seconds_sum 1250.0
rpc_duration_seconds_count 10000
2.6 Prometheus 数据模型:时间序列与标签
Prometheus 的所有指标数据都存储为时间序列(Time Series)。一条时间序列由指标名称(Metric Name)和一组标签(Labels)唯一标识。标签是键值对,用于多维数据模型。
# 时间序列格式
<metric_name>{<label_name>="<label_value>", ...} <value> <timestamp>
# 示例
degraded_requests_total{service="order",degradation_type="timeout",instance="10.0.1.5:8080"} 1024 1700000000
标签是 Prometheus 数据模型的核心能力,支持灵活的聚合与过滤。以下 SVG 图展示了时间序列的组成结构:
2.7 标签设计原则与性能影响
标签是 Prometheus 数据模型中最强大的特性,但滥用标签会导致基数爆炸(Cardinality Explosion),严重影响查询性能与存储效率。以下表格总结了标签设计的最佳实践:
| 原则 | 说明 | 反例 |
|---|---|---|
| 有限基数 | 标签值数量应控制在数千以内 | 使用 user_id 作为标签(百万级) |
| 可枚举 | 标签值应来自预定义的枚举集合 | 使用 request_id 作为标签(无限) |
| 业务语义 | 标签应反映服务、实例、区域等业务维度 | 使用 random_hash 作为标签 |
| 避免冗余 | 不要存储可以从其他标签推导出的信息 | 同时使用 region 和 zone 且一一对应 |
service(服务名)、degradation_type(降级类型:timeout/error/circuit_breaker)、instance(实例地址)、status(成功/失败)作为核心标签。避免将 trace_id 或 user_id 作为标签。
2.8 指标类型与数据模型的关系总结
以下 SVG 图展示了四种指标类型在数据模型中的位置,以及它们如何映射到时间序列: