Prometheus 入门了解
云原生监控的事实标准。这篇讲清楚它的采集模型、数据结构、PromQL 思路和告警链路,不做安装教程。
1 · 一句话理解
Prometheus = 时序数据库 + 定时拉取器 + 查询语言 + 告警引擎,四件事打包在一个二进制里。
它回答的是这类问题:现在系统健康吗?刚才那波超时是从哪开始的?磁盘还有多久写满?
和日志系统(ELK / Loki)的分工要分清:
- 日志回答"具体那一次请求发生了什么",是离散事件
- 指标回答"整体趋势和比例如何",是按时间连续采样的数值
2 · 技术栈定位
- 实现语言:Go,单二进制部署,无外部依赖(自带 TSDB,不需要装数据库)
- 生态位:CNCF 第二个毕业项目(第一个是 Kubernetes),K8s 监控的默认答案
- 接入方式:应用暴露一个
/metrics HTTP 端点即可,各语言都有官方 client library
- 常见搭配:Prometheus 采集 + Grafana 展示 + Alertmanager 告警
3 · 整体架构

最关键的设计是 Pull 模型——Prometheus 主动去目标那里"拉",而不是让目标"推"过来。
Pull 带来的好处:
- 目标是否存活天然可知:拉不到就是挂了,
up 指标自动生成
- 不会被打垮:采集频率由 Prometheus 自己控制,突发流量不会冲垮监控系统
- 调试方便:浏览器直接打开
http://服务:端口/metrics 就能看到全部原始数据
Pushgateway 是例外,不是常态。它只用于生命周期极短的任务(比如跑几秒就退出的定时脚本),因为这类任务根本等不到被拉取。滥用它会导致指标僵死(任务没了指标还在)和单点瓶颈。
4 · 数据模型与指标类型

一条数据长这样:
http_requests_total{method="POST", handler="/api/order", status="500"} 1027 @1699999999
└──────── 指标名 ────────┘└─────────── 标签集 ───────────┘ └值┘ └时间戳┘
标签(label)是 Prometheus 的灵魂,也是最大的坑。指标名相同但标签不同,就是两条完全独立的时间序列。
四种类型的选择原则:
| 类型 |
什么时候用 |
典型例子 |
| Counter |
只会累加的量 |
请求总数、错误总数、字节数 |
| Gauge |
会上下波动的瞬时值 |
内存使用、在线连接数、温度 |
| Histogram |
需要看分布和分位数 |
请求耗时、响应体大小 |
| Summary |
需要精确分位数且不用跨实例聚合 |
单机内部耗时统计 |
Counter 别直接看值。http_requests_total 是一个一直变大的数,本身没意义。要用 rate() 转成"每秒多少次"才有意义。
Histogram 优先于 Summary:前者在服务端算分位数,可以把 10 台机器的数据合起来算全局 P99;后者在客户端就算好了,多台机器的分位数无法求平均(那是数学上错误的)。
5 · PromQL 速览
PromQL 不是 SQL,它的核心是对时间序列做向量运算。
# 每秒请求数(5 分钟窗口的平均增长率)
rate(http_requests_total[5m])
# 错误率:5xx 占比
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m]))
# 按接口分组的 P99 延迟
histogram_quantile(0.99,
sum by (le, handler) (rate(http_request_duration_seconds_bucket[5m])))
# 磁盘 4 小时内会写满的机器
predict_linear(node_filesystem_avail_bytes[1h], 4*3600) < 0
几个必须建立的直觉:
[5m] 叫区间向量,取的是过去 5 分钟的一串采样点,只有它能喂给 rate() / increase()
rate() 自动处理 Counter 重启归零,不用自己判断
sum by (xxx) 是降维,把不关心的标签合并掉;without (xxx) 是反向写法
- 告警表达式要用
for,避免一个毛刺就把人叫醒
6 · 告警链路

职责划分要记住:
- Prometheus 只负责判断"是否该告警",产出 Firing 事件
- Alertmanager 负责"怎么通知人"——去重、分组、抑制、静默、按标签路由
一条告警规则的样子:
- alert: HighErrorRate
expr: sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m])) > 0.05
for: 5m
labels:
severity: critical
annotations:
summary: "5xx 错误率超过 5%,已持续 5 分钟"
for: 5m 是降噪的关键:条件满足后先进入 Pending,熬满 5 分钟还没恢复才真正 Firing。中途恢复就悄悄消失,不打扰任何人。
7 · 存储与规模边界
- 本地 TSDB 默认存 15 天,按 2 小时一个 block 落盘,配合 WAL 防丢
- 单机可承载百万级活跃时序,再多就要考虑分片或换方案
- 不做长期存储:需要存一年就接 Thanos / VictoriaMetrics / Mimir,通过远程写扩展
- 不适合高基数场景:把 user_id、request_id、完整 URL 当标签,序列数会指数爆炸,直接把内存打满
基数爆炸是 Prometheus 最常见的生产事故。判断原则:标签的取值集合必须是有限且可枚举的。状态码、接口名、机房可以;用户 ID、订单号绝对不行。
8 · 什么时候用得上
适合:
- Kubernetes / 微服务集群,需要统一的指标采集和告警
- 需要基于趋势做容量规划和性能分析
- 有多个团队、多套服务需要标准化监控口径
不必要:
- 单机小服务——云厂商自带监控或一个
uptime 检测就够了
- 只想看日志和错误堆栈——那是日志系统和 APM 的活
- 需要精确到每一笔的业务对账——指标是采样聚合,不保证不丢,别拿它当账本
9 · 落地时要注意的坑
- 标签基数必须控制,这是第一红线
- 抓取间隔别太密。15s 是常见起点,5s 以下要算清存储成本
- 告警要分级。critical 打电话、warning 进群、info 只进看板,全都同级等于没有分级
- 监控系统自己也要被监控。Prometheus 挂了没人知道是最尴尬的情况,用另一套或 Alertmanager 的 watchdog 兜底
- 默认无鉴权。
/metrics 和 Web UI 都不要直接暴露公网,指标里往往泄露内网拓扑
- Grafana 面板别堆一百个图。先定 SLI,围绕黄金四指标(延迟、流量、错误、饱和度)建面板
小结:Prometheus 是"用有限维度的数值,持续描述系统状态"的工具。用好它的前提不是学会 PromQL,而是想清楚你真正需要盯的是哪几个数——指标定得对,简单查询就够用;指标定得乱,再复杂的表达式也救不回来。