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),就唯一确定了一条时间序列。标签是键值对,用来区分不同的维度。比如上面的 methodendpointstatus

我的经验:标签设计是 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 就跟玩一样。