2. Prometheus基础:架构设计、数据模型、Pull模式与Push模式对比
聊到监控系统,Prometheus 现在几乎是绕不开的话题。我记得最早接触它的时候,还是因为公司要替换掉那套老旧的 Zabbix,当时我第一反应是:又一个轮子?结果深入了解后,我发现这玩意儿的设计思路确实有点东西。
今天咱们就掰开揉碎,把 Prometheus 的架构、数据模型,还有那个经典的 Pull vs Push 之争,一次性讲清楚。
2.1 Prometheus 整体架构设计
先看一张架构图(脑补一下):Prometheus Server 是核心,它负责拉取数据、存储数据、提供查询。周边围绕着各种 Exporter(数据采集器)、Alertmanager(告警管理器)、Pushgateway(短任务推送网关),以及 Grafana 这样的可视化工具。
说白了,整个体系就是:采集 → 存储 → 查询 → 告警 → 可视化。
我个人习惯把 Prometheus 比作一个「数据调度中心」。它不主动生产数据,而是定期去各个数据源「拿」数据。这个「拿」的动作,就是 Pull 模式的核心。
核心组件一览:
- Prometheus Server:负责数据拉取、存储、查询。包含时序数据库(TSDB)和 HTTP Server。
- Exporter:将各种非原生 Prometheus 指标(如 MySQL、Nginx、Linux 系统)转换成 Prometheus 能识别的格式。
- Pushgateway:用于接收短生命周期任务(如批处理作业)推送的指标。
- Alertmanager:处理告警,负责去重、分组、路由到钉钉、邮件等渠道。
- Grafana:可视化面板,虽然不归 Prometheus 管,但几乎是标配。
嗯,这里要注意:Prometheus 的存储是本地磁盘,单机性能有限。如果你要搞大规模集群,就得考虑 Thanos 或 VictoriaMetrics 这类扩展方案了。我在项目中就吃过单机存储的亏,数据量一上来,查询直接超时。
2.2 数据模型:时间序列与标签
Prometheus 的数据模型,核心就一句话:一切皆时间序列。
什么是时间序列?就是一组带时间戳的数值,按时间顺序排列。比如:
http_requests_total{method="GET", endpoint="/api/v1/users", status="200"} 1024 @ 1700000000
http_requests_total{method="GET", endpoint="/api/v1/users", status="200"} 1030 @ 1700000015
你看,一个指标名 + 一组标签(Label),就唯一确定了一条时间序列。标签是键值对,用来区分不同的维度。比如上面的 method、endpoint、status。
我的经验:标签设计是 Prometheus 使用中最容易踩坑的地方。标签值不要太多,比如把用户 ID 这种高基数(High Cardinality)数据当标签,会导致内存爆炸。我曾经见过一个同事把请求的 IP 地址直接当标签,结果 Prometheus 直接 OOM 了。
Prometheus 的数据模型有四种指标类型:
| 类型 | 说明 | 典型场景 |
|---|---|---|
| Counter | 只增不减的计数器 | 请求总数、错误总数 |
| Gauge | 可增可减的仪表盘 | CPU 使用率、内存使用量 |
| Histogram | 直方图,统计分布 | 请求延迟分布、响应大小分布 |
| Summary | 类似 Histogram,但计算分位数 | 请求延迟的 P99、P95 |
你想想看,Counter 适合统计「总量」,比如累计请求数;Gauge 适合看「当前值」,比如内存占用。Histogram 和 Summary 则用来做性能分析,比如「99% 的请求在 200ms 内完成」。
2.3 Pull 模式 vs Push 模式
这是 Prometheus 最核心的设计哲学之一。说白了,就是数据怎么进到 Prometheus 里。
Pull 模式(Prometheus 默认)
Prometheus Server 主动去各个目标(Target)拉取数据。目标需要暴露一个 HTTP 端点,比如 /metrics。
# Prometheus 配置示例
scrape_configs:
- job_name: 'node_exporter'
static_configs:
- targets: ['localhost:9100']
优点很明显:
- 可控性强:Prometheus 自己决定拉取频率,不会因为目标端压力大而疯狂推送。
- 健康检查:拉取失败说明目标挂了,天然就是告警信号。
- 配置简单:只要目标暴露了端口,Prometheus 就能找到它。
缺点也有:
- 网络限制:目标必须能被 Prometheus 访问到。跨网络、跨机房就麻烦了。
- 短任务不友好:一个批处理脚本跑几秒就结束了,Prometheus 还没拉取呢,任务已经没了。
Push 模式(通过 Pushgateway)
对于短任务,Prometheus 提供了 Pushgateway 作为中转。任务主动把指标推送到 Pushgateway,Prometheus 再从 Pushgateway 拉取。
# 示例:推送指标到 Pushgateway
echo "job_duration_seconds 42" | curl --data-binary @- http://pushgateway:9091/metrics/job/my_batch_job
优点:
- 短任务友好:任务跑完前把数据推出去,不会丢失。
- 网络灵活:只要 Pushgateway 可达,任务可以在任何地方。
缺点:
- 单点故障:Pushgateway 挂了,所有推送都失败。
- 数据堆积:如果任务一直推送,Pushgateway 内存会涨。
- 无法健康检查:Prometheus 不知道任务是否还活着。
避坑指南:我曾经在项目中过度依赖 Pushgateway,把所有指标都往里面推。结果 Pushgateway 内存飙升,Prometheus 拉取时还经常超时。后来我反思了一下:能 Pull 就别 Push。Pushgateway 只适合短任务,别把它当万能网关用。
Pull vs Push 对比总结
| 维度 | Pull 模式 | Push 模式 |
|---|---|---|
| 数据采集方式 | Server 主动拉取 | 目标主动推送 |
| 适用场景 | 长期运行的服务、基础设施 | 短任务、批处理、网络隔离环境 |
| 健康检查 | 天然支持(拉取失败即异常) | 不支持(需要额外心跳) |
| 配置复杂度 | 低(只需配置 targets) | 中(需要维护 Pushgateway) |
| 数据丢失风险 | 低(拉取失败可重试) | 高(推送失败数据丢失) |
| 扩展性 | 好(可水平扩展) | 差(Pushgateway 易成瓶颈) |
我个人习惯是:80% 的场景用 Pull,20% 的短任务场景用 Push。比如监控 MySQL、Nginx、Linux 系统,全部用 Exporter + Pull。只有那些定时脚本、批处理任务,才考虑 Pushgateway。
2.4 小结
Prometheus 的架构设计,说白了就是围绕「Pull 模式」展开的。数据模型用标签来区分维度,灵活但要注意基数问题。Pull 和 Push 各有优劣,但记住一点:Prometheus 天生是为 Pull 设计的,别强行 Push。
下一章,咱们会深入 PromQL 查询语言,到时候你会发现,理解了数据模型,写 PromQL 就跟玩一样。