跳转到内容

Prometheus — 时序监控系统

是什么

Prometheus 是 SoundCloud 2012 年开发的「主动拉取(pull)+ 时序数据库 + PromQL 查询」监控系统。

日常类比:

  • 以前的监控像每个员工主动汇报工作(push)——员工不汇报,经理就不知道他在干嘛
  • Prometheus 是经理巡检办公桌(pull metrics endpoint)——每隔 15 秒上门看一眼,不汇报的员工立刻发现

每个被监控的服务暴露一个 /metrics 端点,Prometheus 主动来拉。它把拉到的数字按时间轴存进自己的时序数据库,配合 PromQL 这门查询语言,可以问”过去 5 分钟错误率是多少”、“内存涨速正常吗”。

为什么重要

  • CNCF 第二个毕业项目:仅次于 kubernetes,地位相当于云原生世界的”监控官方认证”
  • 云原生监控事实标准kubernetes / Istio / Linkerd 都内置 /metrics 端点;装好集群基本就插上 Prometheus
  • PromQL 时序查询语言rate 算速率、histogram_quantile 算 P99 延迟,原生为时序数据设计
  • Grafana 黄金组合:Prometheus 存数据,Grafana 画看板——业内默认配置
  • 会写 promql 是 SRE 的硬指标:面试基本必问,不会等于不会运维

核心要点

Pull-based scraping(主动拉取)

Prometheus 不等服务上报,自己定期上门。配置里写:「每 15 秒去 app:8080/metrics 拉一次」。

好处

  • 服务只需暴露端点,不用配 Prometheus 地址(解耦)
  • Prometheus 知道服务是否健康(拉不到就标记 up=0
  • 拉取节奏 Prometheus 控制,不会被推爆

对比 push 模式(StatsD / OpenTelemetry push):push 模式服务主动发,Prometheus 模式服务被动等。

时序数据模型

每条数据长这样:

http_requests_total{method="GET", status="200", path="/api/users"} 1027 1716969600
└────── metric ────┘└────────── labels ────────────┘ └ value ┘└─ timestamp ─┘
  • metric_name:度量名,比如 http_requests_total
  • labels:键值对维度,可以按 method / status / path 切分
  • value:当前数值(计数器、仪表盘、直方图都行)
  • timestamp:采样时间

同一个 metric_name 加不同 label 组合,就是不同的时序——这是后面”基数爆炸”踩坑的源头。

PromQL(时序查询语言)

PromQL 专为”按时间问问题”设计:

# 5 分钟内 5xx 错误率
rate(http_requests_total{status=~"5.."}[5m])
# P99 延迟
histogram_quantile(0.99, rate(http_request_duration_bucket[5m]))
# 按服务分组求和
sum by (service) (rate(http_requests_total[1m]))

rate / sum / histogram_quantile 是高频三件套,会这三个就能写 80% 的告警。

实践案例

案例 1:起一个 Prometheus

Terminal window
docker run -p 9090:9090 prom/prometheus

打开 http://localhost:9090 ——自带的 web UI,可以直接写 PromQL 查询、看 target 状态。Prometheus 会先 scrape 自己(它自己也有 /metrics),所以马上就有数据可查。

案例 2:让 Prometheus 拉你的应用

prometheus.yml

scrape_configs:
- job_name: 'app'
scrape_interval: 15s
static_configs:
- targets: ['app:8080']

应用侧用 prom-client(Node)或 prometheus_client(Python)暴露 /metrics

const client = require('prom-client')
const counter = new client.Counter({ name: 'http_requests_total', help: '...', labelNames: ['status'] })
counter.inc({ status: '200' })
// GET /metrics 自动返回 Prometheus 格式

15 秒后 Prometheus 就开始拉数据。

案例 3:写一个错误率告警

rate(http_requests_total{status=~"5.."}[5m])
/ rate(http_requests_total[5m]) > 0.05

读法:「5 分钟内 5xx 占比超过 5%」。配进 Alertmanager,超过阈值发 Slack。

踩过的坑

  1. Cardinality 爆炸:把 user_id 这种唯一值放 label —— 1000 万用户 = 1000 万时序。Prometheus 内存爆掉,查询变慢。规则:label 值的取值集合必须是有限可枚举的(status / method / endpoint 模板 OK;user_id / request_id / 完整 URL 不行)。

  2. Pull 模式不适合短任务:Cron job 跑 30 秒就退出,Prometheus 还没来得及 scrape。解法:用 Pushgateway 做桥接——任务 push 到 Pushgateway,Prometheus 从 Pushgateway pull。

  3. 单实例 ≠ HA:Prometheus 默认单机存储,挂了就断数据。生产要 HA:跑两台同配置 + Thanos / Cortex / Mimir 做集群和长期存储。

  4. 长期存储贵:默认本地保留 15 天,再长就要远程存储(Thanos 写 S3 / Cortex 写对象存储)。原始 scrape 数据量大,要会用 recording rule 预计算降采样。

  5. PromQL rate vs increase 容易混rate 算每秒速率,increase 算窗口总增量。监控速率用 rate,做业务统计用 increase

适用 vs 不适用

适用

  • 容器化 / 微服务监控(kubernetes / Docker / 服务网格);数值指标(CPU / QPS / 延迟)
  • 中短期数据(默认 15 天);拉模式可达的服务

不适用

  • 日志(用 Loki / elasticsearch
  • 链路追踪(用 Jaeger / Tempo)
  • 高基数事件分析(用户行为分析用 clickhouse
  • 移动端 / 浏览器监控(push 模式更合适)
  • 强一致性的财务数据(Prometheus 优先可用性,会丢点)

历史小故事

  • 2012:SoundCloud 工程师 Matt Proud 和 Julius Volz 受 Google Borgmon 启发,在内部造了 Prometheus
  • 2015 年初:开源
  • 2016:加入 CNCF,成为继 kubernetes 之后第二个项目
  • 2018:从 CNCF 毕业,和 kubernetes 形成”K8s + Prometheus”的云原生标配
  • 2024:Prometheus 3.0 发布——加 OTel-native(直接吃 OpenTelemetry 数据)+ 历史数据查询优化

学到什么

  • pull vs push:pull 让监控系统主动发现服务死活;cardinality = label 笛卡尔积
  • PromQL 把时间窗口/速率/分位数做成一等公民;CNCF 顺序:kubernetes → Prometheus → 其他

延伸阅读

关联

  • kubernetes —— K8s 集群默认监控方案就是 Prometheus
  • docker —— docker run prom/prometheus 是上手最快路径
  • nginx —— Nginx 暴露 stub_status,Prometheus exporter 转成 metrics
  • caddy —— Caddy 自带 /metrics 端点,开箱即用
  • clickhouse —— 长期高基数数据用 ClickHouse 补 Prometheus 短板
  • elasticsearch —— 日志走 ES,指标走 Prometheus,分工清晰

反向链接

  • besu —— Hyperledger Besu — 用 Java 写的以太坊客户端
  • btop —— btop — bashtop 三代 C++ 版,五面板一屏的彩色资源监控器
  • caddy —— Caddy — 自动 HTTPS Web 服务器
  • calico —— Calico — 用 BGP 路由把 K8s pod 当成一个个小路由器
  • cilium —— Cilium — 用 eBPF 把 K8s 网络从 iptables 时代搬出来
  • clickhouse —— ClickHouse — 列式 OLAP 数据库
  • datadog —— Datadog — 把所有监控装进一个仪表盘的 SaaS 标杆
  • dropwizard —— Dropwizard — Java 微服务的”开箱即用 12-factor 起步包”
  • elasticsearch —— Elasticsearch — 分布式搜索引擎
  • fluent-bit —— Fluent Bit — C 写的轻量日志 forwarder,K8s DaemonSet 默认选
  • gin —— Gin — Go 写 web API 的事实标准框架
  • glances —— Glances — Python 写的全栈系统监控(终端 + Web + REST + 远程)
  • go-zero —— go-zero — 一份契约文件生成整套 Go 微服务
  • grafana —— Grafana — 监控可视化看板
  • grafana-tempo —— Grafana Tempo — 用对象存储装下你所有的 trace
  • influxdb —— InfluxDB — 专用时序数据库
  • istio —— Istio — 给微服务装一层透明的网络治理面
  • jaeger —— Jaeger — 分布式追踪系统
  • k6 —— k6 — 用 JS 写脚本的现代负载测试器
  • kratos —— kratos — Go 微服务一锅出 HTTP 和 gRPC 两份服务
  • kubernetes —— Kubernetes — 容器编排平台
  • langfuse —— Langfuse — LLM 应用可观测性
  • lazydocker —— lazydocker — Go 写的 Docker TUI,五面板看容器 / 镜像 / 网络 / 卷
  • loki —— Loki — 给日志做 Prometheus,只索引标签不索引内容
  • m3 —— M3 — Uber 的分布式 TSDB
  • mongo —— MongoDB — 文档数据库服务端开源实现
  • nethermind —— Nethermind — .NET 写的高性能以太坊客户端
  • nginx —— nginx — 高性能 Web 服务器
  • opensearch —— OpenSearch — AWS 主导的 Apache 2.0 搜索引擎分叉
  • opentelemetry —— OpenTelemetry — 让所有应用用同一种语言吐监控数据
  • opentelemetry-collector —— opentelemetry-collector — OTel 官方核心仓库与组件模型
  • opentsdb —— OpenTSDB — HBase 上的第一代分布式 TSDB
  • otel-collector —— OpenTelemetry Collector — 可观测性数据的统一中转站
  • robyn —— Robyn — Rust 运行时的高性能 Python Web 框架
  • signoz —— SigNoz — 自托管的 OpenTelemetry 一体化可观测平台
  • tdengine —— TDengine — 一个设备一张表的国产 IoT 时序库
  • tempo —— Tempo — 把分布式追踪扔进 S3 的开源后端
  • terraform —— Terraform — 基础设施即代码
  • vector —— Vector — Rust 写的统一可观测性数据管道
  • victoriametrics —— VictoriaMetrics — 高性能 Prometheus 替代