4、Prometheus核心概念:数据模型与指标类型
聊监控,绕不开 Prometheus。在特征平台里,它几乎就是标配。今天我把它的核心概念拆开揉碎了讲一遍。这些东西你搞懂了,后面搭建 SLA 监控面板才会顺手。
4.1 数据模型:Metric 与 Label
Prometheus 的数据模型,说白了就是一个带标签的时间序列。
时间序列是什么?就是同一指标在不同时间点的取值集合。每个时间序列由两部分组成:指标名(Metric) 和 标签(Label)。
举个例子:
feature_store_request_total{method="GET", endpoint="/api/v1/features", status="200"} 1024
这里 feature_store_request_total 是指标名,{method="GET", endpoint="/api/v1/features", status="200"} 是标签集合,1024 是当前值。
我个人习惯把标签分成两类:
- 标识性标签:比如
instance、job,用来唯一确定监控目标 - 维度标签:比如
method、status、endpoint,用来做聚合分析
你想想看,为什么 Prometheus 要设计成这种模型?因为它要支持灵活的聚合查询。你可以通过标签任意组合,从不同维度看数据。比如:
- 只看 GET 请求的总数:
sum(feature_store_request_total{method="GET"}) - 按状态码分组:
sum by(status) (feature_store_request_total)
4.2 四种指标类型
Prometheus 提供了四种指标类型。我刚开始接触时也觉得有点绕,但用多了就发现,每种类型都有它最合适的场景。
| 类型 | 特点 | 典型场景 | 注意事项 |
|---|---|---|---|
| Counter | 只增不减,重启归零 | 请求总数、错误总数 | 不能用来算当前值,要用 rate() 算速率 |
| Gauge | 可增可减,反映当前状态 | CPU 使用率、内存占用、队列长度 | 直接取值即可,不需要 rate() |
| Histogram | 分桶统计,可算分位数 | 请求延迟、响应大小 | 桶的区间要合理设置,否则浪费资源 |
| Summary | 客户端预计算分位数 | 延迟分位数(p99/p95) | 分位数在客户端算,服务端无法聚合 |
4.2.1 Counter:只增不减的计数器
Counter 是最简单的类型。它只记录累计值,比如总请求数、总错误数。你没法直接用它看当前 QPS,得配合 rate() 或 increase() 函数。
# 定义 Counter
feature_store_request_total = Counter('feature_store_request_total', 'Total requests', ['method', 'endpoint', 'status'])
# 查询:过去 5 分钟的平均 QPS
rate(feature_store_request_total[5m])
4.2.2 Gauge:可上可下的仪表盘
Gauge 反映的是当前值。比如内存使用量、在线连接数、队列深度。它不需要 rate(),直接取值就行。
# 定义 Gauge
feature_cache_memory_bytes = Gauge('feature_cache_memory_bytes', 'Current cache memory usage', ['cache_name'])
# 查询:当前缓存使用量
feature_cache_memory_bytes{cache_name="online"}
嗯,这里要注意:Gauge 虽然简单,但容易踩坑。我遇到过一个问题——Gauge 的更新频率太低,导致告警延迟。比如你每 60 秒才更新一次内存值,那内存突增时,告警可能要等 1 分钟才能触发。
4.2.3 Histogram:分桶统计的艺术
Histogram 是四种类型里最复杂的,也是最强大的。它把观测值放入预定义的桶(Bucket)里,然后统计每个桶的计数。
# 定义 Histogram,桶区间为 0.1, 0.5, 1.0, 2.5, 5.0, 10.0 秒
feature_request_duration_seconds = Histogram(
'feature_request_duration_seconds',
'Request latency in seconds',
['method', 'endpoint'],
buckets=[0.1, 0.5, 1.0, 2.5, 5.0, 10.0]
)
用 Histogram 算 p99 延迟:
histogram_quantile(0.99, sum(rate(feature_request_duration_seconds_bucket[5m])) by (le))
4.2.4 Summary:客户端预计算的分位数
Summary 和 Histogram 都能算分位数,但有个本质区别:Summary 在客户端就计算好了分位数,服务端直接拿结果。而 Histogram 只存桶计数,分位数在查询时计算。
# 定义 Summary,计算 p50、p90、p99
feature_request_duration_summary = Summary(
'feature_request_duration_summary',
'Request latency summary',
['method', 'endpoint'],
quantiles=[0.5, 0.9, 0.99]
)
Summary 的好处是查询快,但坏处也很明显——你没法跨实例聚合分位数。比如你有 10 个实例,每个实例的 p99 是 1 秒,但全局 p99 可能是 5 秒。Summary 算不出来这个全局值。
4.3 Pull 模型与 Pushgateway
Prometheus 默认是 Pull 模型——它主动去拉取目标的数据。但有些场景下,目标没法被直接拉取,比如批处理任务、短生命周期任务。这时候就需要 Pushgateway 了。
4.3.1 Pull 模型:谁拉谁主动
Pull 模型的工作流程很简单:
- Prometheus Server 根据配置,定期访问目标的
/metrics端点 - 目标返回当前所有指标数据
- Prometheus 存储并处理这些数据
Pull 模型的好处:
- 你可以在 Prometheus 端控制采集频率,统一管理
- 目标挂了,Prometheus 能立刻发现(采集超时)
- 不需要在目标端安装额外的推送组件
但 Pull 模型也有局限。比如你有一个定时任务,跑 10 秒就结束了。Prometheus 还没来拉取,任务已经退出了。这时候就需要 Pushgateway。
4.3.2 Pushgateway:临时任务的救星
Pushgateway 是一个中间代理。任务把指标推送给 Pushgateway,Prometheus 再从 Pushgateway 拉取。
# 批处理任务结束时,推送指标到 Pushgateway
echo "feature_etl_duration_seconds 120.5" | curl --data-binary @- http://pushgateway:9091/metrics/job/feature_etl
我曾经踩过这个坑。一个 ETL 任务崩溃了,但 Pushgateway 里还留着它上次成功运行的指标。结果监控面板显示一切正常,直到用户反馈数据没更新,我们才发现问题。
解决方案:在任务启动时,先清理旧的指标,或者给指标加上时间戳,配合 max_over_time 函数做判断。
4.4 知识体系总览
下面这张图把本章的核心概念串起来了。你可以看到数据模型、指标类型、采集模型之间的关系。
这张图把三个核心模块串起来了。数据模型是基础,指标类型是工具,采集模型是手段。三者配合,才能构建出完整的监控体系。
好了,这一章的内容就到这里。Prometheus 的数据模型和指标类型是后续所有监控工作的基石。你把这些概念吃透了,后面搭建 SLA 监控面板、配置告警规则,都会顺手很多。