# 第 1 章 Prometheus 入门:从监控到可观测性
本章导读
如果你已经学过 Zabbix,第一个问题大概率是:"既然有 Zabbix 了,为什么还要再学一套 Prometheus?"
本章就从这个疑问出发,先把" 监控 " 这件事放回到更大的框架 —— 可观测性里去看,再落到 Prometheus 本身:它是什么、由哪些组件拼成、数据怎么流转、模型长什么样。本章是整门课的地基。地基打不牢,后面装 Exporter、写 PromQL、配告警、接 Grafana 都会变成 "照着敲命令",一旦报错就无从下手。
学习目标
| 序号 | 学完本章,你应当能够 |
|---|---|
| 1 | 说清可观测性三大支柱,以及 Zabbix / Prometheus 分别属于哪一支 |
| 2 | 画出完整监控系统的六大环节,并说明每个环节解决什么问题 |
| 3 | 用 "四个黄金指标" 设计一套自己的监控项清单 |
| 4 | 解释时序数据库为什么比关系型数据库更适合监控场景 |
| 5 | 讲清 Prometheus 的组件构成与四条工作流程 |
| 6 | 对比 Pull 与 Push 两种采集模型,回答 "Zabbix 与 Prometheus 的区别" 这道必考题 |
| 7 | 看懂一条 Prometheus 指标的含义:metric 名 + 标签 = 唯一的 time series |
# 1.1 先破一个误解:Prometheus 不是 Zabbix 的替代品
很多同学下意识地把新技术当成旧技术的 "升级包":有了 Prometheus,Zabbix 就该淘汰了。
不是这样的。 在真实的互联网公司里,这两个监控系统往往是并存的,有些大厂甚至是 "两套都跑、各管一摊"。
原因在于它们的技术基因不同:
- Zabbix 诞生在 "物理机 + 虚拟机" 的时代,历史悠久、生态成熟稳定,最擅长监控传统形态的东西 —— 物理服务器、交换机、路由器、存储设备这类固定资产,以及运行在固定 IP 上的传统服务。它对 SNMP、IPMI 这类硬件协议的支持非常完备。
- Prometheus 诞生在容器化 / 云原生时代,天生就是为 " 目标会动态变化 "的环境设计的。容器今天跑在这台机器、明天漂到那台机器,IP 一直在变,靠" 提前把 IP 写进配置文件 " 的方式根本跟不上节奏。
一句话概括:
Zabbix 擅长 "管得住的固定目标",Prometheus 擅长 "抓不住的动态目标"。
当然,这并不意味着 Prometheus 不能监控传统服务器 —— 它当然能, node_exporter 就是干这个的。也不是说 Zabbix 不能监控容器 —— 只是要费很大劲。
┌────────────────────────────────────────────────────────┐
│ 一家中大型公司的典型监控版图 │
├────────────────────────────────────────────────────────┤
│ 机房 / 网络设备 / 老旧业务 ──► Zabbix │
│ 容器平台 / 微服务 / K8s ──► Prometheus + Grafana │
└────────────────────────────────────────────────────────┘
另外要提醒一句:"Prometheus" 这个名字,指的其实不是一个软件,而是一整套组件的集合。 这一点和 Zabbix 很像 ——Zabbix 也是一堆东西: zabbix-server 、 zabbix-agent 、 zabbix-proxy 、 zabbix-web 、 zabbix-java-gateway ,还得配一个 MySQL。Prometheus 同理,只是因为它在这套架构里分量最重,所以大家习惯用它的名字指代整个体系。
# 1.2 把眼界放宽:什么是可观测性
# 1.2.1 从控制论说起
可观测性(Observability) 这个词并不是 IT 行业发明的,它诞生于几十年前的控制理论,指的是:
通过检查系统的 "输出",来推断系统 "内部状态" 的能力。
输出能反映内部状态的程度越高,系统的可观测性就越好。
举个生活化的例子:你发烧了,医生不能直接 "看见" 你体内的炎症,但他可以通过体温、血常规、心率这些外部输出去推断。这些可测量的输出越丰富、越精确,诊断就越准。系统运维完全是同一个道理 —— 你没法钻进服务器里看它 "心情如何",只能靠它吐出来的数据判断。
📌 里程碑事件:2018 年,CNCF(云原生计算基金会)率先把 "可观测性" 引入 IT 领域,称其为云原生时代必须具备的能力,并出版《可观测性白皮书》做了系统阐述。
# 1.2.2 可观测性三大支柱(三大信号)
白皮书提出的 "可观测性三大信号",今天已经是 IT 领域的通识:
| 支柱 | 回答的问题 | 数据特征 | 代表工具 |
|---|---|---|---|
| 指标 Metrics | 系统 "现在怎么样"? | 数值型、有明确时间戳、可聚合 | Prometheus、Zabbix |
| 日志 Logging | "究竟发生了什么"? | 离散事件明细、文本、体量大 | ELK(Elasticsearch + Logstash + Kibana)、Loki |
| 追踪 Tracing | 一次请求 "经过了谁"? | 调用链路、有父子关系与耗时 | SkyWalking、Jaeger、Zipkin |
三者是互补关系,不是替代关系:
- 指标告诉你 "CPU 用了 95%"—— 发现异常;
- 日志告诉你 "95% 是因为某个 SQL 死循环"—— 定位原因;
- 追踪告诉你 "这个 SQL 是在 A→B→C 这条链路里被 C 调用的"—— 锁定位置。
⚠️ 注意:Zabbix 和我们今天要学的 Prometheus,都只属于第一支柱 —— 指标监控。
日志监控要靠 ELK,链路追踪要靠 SkyWalking。这两块不在本课程范围内,但它们是你在简历和面试里非常值钱的加分项,建议课外补齐。
# 1.3 一个完整监控系统的六大环节
不管用什么工具,一个完整的监控系统,数据都要依次流过下面六个环节:
flowchart LR | |
A["① 数据来源<br/>产生 / 暴露"] --> B["② 数据采集<br/>周期抓取"] | |
B --> C["③ 数据存储<br/>TSDB"] | |
C --> D["④ 数据处理<br/>聚合 / 计算"] | |
D --> E["⑤ 展示分析<br/>图形化"] | |
E --> F["⑥ 告警<br/>阈值触发通知"] |
把这六环背下来,你就能在任何监控产品上 "对号入座"—— 看任何一个新工具,只要问自己:它负责这六环里的哪一环?剩下的靠谁补?架构立刻清晰。
# 1.3.1 ① 数据来源:数据从哪来
要监控,首先得有数据。数据常见的产生与暴露方式有三类:
- 硬件本身的记录信息 —— 以文件或内存属性的形式存在(比如
/proc下的各种内核指标); - 应用业务的接口 —— 主动暴露软件自身的运行状态,例如
redis info、各类/status端点; - 相关的信息采集工具 —— 方便采集数据的系统级命令或采集器。
这里有一个关键概念:这些数据在长时间运行中,都是以固定的 "属性指标" 来描述它们的,我们称之为 metric。
监控系统要做的事,就是对每个环境、每个指标都持续获取数据,并按用户需要的方式提供出去。
# 1.3.2 ② 数据采集:怎么把数据拿过来
指标数据不是取一次就完事,而是要持续、周期性地采集。按采集通道划分,分为两大类:
软件方式
| 方式 | 说明 |
|---|---|
| agent | 专用的采集代理,装在目标机上,如 Zabbix Agent、node_exporter |
| http | 基于 HTTP 协议拉取(Prometheus 的主流方式) |
| ssh | 常见的系统通信机制,但并非所有系统都支持,效率也偏低 |
| SNMP | 简单网络管理协议(Simple Network Management Protocol),广泛内置于交换机、路由器等网络设备 |
硬件方式
| 方式 | 说明 |
|---|---|
| IPMI | 智能平台管理接口(Intelligent Platform Management Interface),工业标准,用于采集硬件物理健康数据:温度、电压、风扇转速、电源状态等 |
💡 关于 IPMI 的一个实战价值:服务器主板上通常有一块独立的带外管理卡(BMC)。它走独立网络,即使业务网络断了,你依然能连上去远程开机、关机、重启、装系统、看硬件告警。机房排障时,这是救命通道。
❗ 为什么采集量会爆炸? 因为每个业务场景需要采集的指标数量并不确定,有时一个业务场景就要采几百个指标。再乘上 "周期性采集",数据量是极其可观的。这就直接引出了下一个环节 —— 存储。
# 1.3.3 ③ 数据存储:为什么必须是时序数据库
我们采集到的是 "样本数据"(sample),单个样本几乎没有意义,必须存下来,后续才能做聚合分析。而且使用这些数据时,不仅要知道值是多少,还必须知道 "这是什么时候的值"。
所以监控数据天然带一个时间维度,我们称之为时间序列数据(Time Series Data,TS),专门存储这类数据的数据库叫时序数据库(Time Series Database,TSDB)。
时序数据库的定义:用于存储时间序列数据,并以时间(时间点或时间区间)建立索引的软件。
对比一下就很清楚了:
| Zabbix | Prometheus | |
|---|---|---|
| 后端存储 | 关系型数据库(MySQL 等) | 内置 TSDB(时序数据库) |
| 是否需要单独部署数据库 | 需要 | 不需要,自身即数据库 |
| 面向场景 | 通用型,什么都能塞 | 专为监控场景优化 |
这是 Prometheus 一个非常特殊、也非常重要的设计:它是监控系统,同时它自己就是数据库。 装完 Prometheus,你就同时拥有了采集器和存储,不用再单独折腾一个 MySQL。
时序数据库的细节,我们在 1.5 节专门展开。
# 1.3.4 ④ 数据处理:原始数据往往没有意义
采集到的原始数据,本身常常说明不了问题,需要经过聚合、计算、切割才可用于分析。
举个贯穿全书的例子。假设我们要判断 "主机内存是否吃紧",直觉上会盯住 "内存可用率":
当它超过 70%(等价于可用率低于 30%)时告警。
你看,这个 70% 并不是采集上来的,而是算出来的。这就是数据处理的典型场景:把两个原始指标做一次运算,得到一个有业务含义的新指标,再交给告警规则去判断。
# 1.3.5 ⑤ 数据展示:人眼看不完的数字
无论是原始时序数据,还是聚合后的统计结果,数据量都极其巨大。几万条数据用表格去看,是看不出来的 —— 肉眼看不出趋势和拐点。
所以可视化不是 "锦上添花",而是监控系统的必需品:把数据画成折线图、柱状图、饼图、热力图,趋势和异常才一眼可见。
Prometheus 的做法很 "洒脱":它自己不做图形界面(只带一个非常简陋的 Web UI 用来调试),把可视化这块整体外包给了 Grafana。而 Zabbix 是自带图形功能的。
这正是 Prometheus"功能不完整" 这一特点的来源 —— 后面还会提到。
# 1.3.6 ⑥ 告警:让系统主动来找你
监控系统最核心的价值之一,是在你不盯着屏幕的时候替你盯着。
做法是:根据日常采集的数据,分析出 "正常状态" 的取值区间,把它设为一个阈值。之后每次采集到实时数据,都拿它与阈值比较,一旦越界,就通过告警机制通知到人。
常见通知渠道:邮件、短信、钉钉、企业微信、电话、Webhook。
在 Prometheus 体系里,这件事被拆成两半:
- Prometheus Server:按告警规则周期性计算,只负责产生告警指示;
- Alertmanager:接收告警后做去重、分组、抑制、路由,再决定发给谁。
# 1.4 监控什么,以及怎么监控
# 1.4.1 监控内容:面试常问的 "你们公司都监控了什么"
"贵公司监控了哪些东西?"—— 这是运维岗的高频面试题。回答不好,会显得你只是 "会点软件"。下面这个三层框架可以直接拿去用。
# 第一层:资源数据(系统级)
- 硬件设备:服务器、路由器、交换机、IO 系统
- 系统资源:OS、网络、容器、VM 实例
- 应用软件:Nginx、MySQL、Redis、Java 应用等
# 第二层:业务服务
- 业务状态:服务通信、服务运行、服务下线、性能指标、QPS、DAU(日活)、转化率
- 业务接口:登录、注册、聊天、留言等关键接口的成功率与耗时
- 经营指标:产品转化率、充值额度、用户投诉量
- 一般故障:访问缓慢、存储空间不足、数据同步延迟、主机宕机、主机不可达
- 严重故障:服务不可用、集群故障
💡 加分点:能说出 " 监控要区分技术指标和业务指标 ",说明你不是只会看 CPU 内存。面试官听到" 我们监控了支付成功率而不是只监控数据库连接数 ",好感度会明显上升。
# 第三层:趋势分析
- 数据统计:以时间序列形式展示历史数据
- 数据预测:事件什么时候会发生、会持续多久、发生概率多大
最典型的应用是容量预测:观察一段时间内磁盘增长曲线,推算 "还有多少天写满",提前扩容。等到真写满了再去处理,业务已经中断了。
# 1.4.2 监控方法:Google 的四个黄金指标
Google 提出了一套用来衡量服务级别健康状况的方法论,叫四个黄金指标(Four Golden Signals)。它特别适合应用与服务层面的监控。
# ① 延迟(Latency)
- 服务处理请求所需的时间,例如 HTTP 请求的平均延迟;
- 应用响应时间会受到所有核心资源的影响:网络、存储、CPU、内存;
- ❗ 关键要求:必须区分成功请求的延迟和失败请求的延迟。
为什么?因为失败请求往往 "很快"—— 连接直接被拒绝,耗时 1ms。如果你把成功和失败的延迟混在一起算平均值,一个大量报错的服务会显得 "响应飞快",这是极其危险的误导。
# ② 流量(Traffic / 吞吐量)
- 衡量服务的容量需求;
- 常见形式:每秒 HTTP 请求数(QPS)、数据库每秒事务数(TPS)、每秒 API 调用数。
# ③ 错误(Errors)
- 失败请求的数量,通常用绝对值或错误率百分比表示;
- 包含三种形态:
- 显式失败:HTTP 500、连接超时;
- 隐式失败:返回 200 但内容是错误页 / 无效内容;
- 策略性失败:按业务约定算失败,例如 "响应时间超过 30ms 即视为失败"。
# ④ 饱和度(Saturation)
- 衡量资源的 "满" 的程度,也就是利用率;
- 覆盖 CPU(容量、配额、节流)、内存(容量、分配)、存储(容量、分配、IO 吞吐)、网络;
- 典型指标:CPU 使用率、内存使用率、磁盘使用率、IO 利用率。
📌 方法论怎么用:这四个指标不是让你死记,而是给你一个设计监控项的检查表。以后设计任何一套监控,先问四句:
它慢吗?它忙吗?它错吗?它满吗?
需要说明的是,成熟公司通常已经有现成的监控指标清单(Excel 表格列几百项),而且 Zabbix 的模板里也内置了海量指标。你不必全都监控 —— 监控项过多会显著加重负担。挑关键的监控,不重要的不兼顾,这也是为什么你需要学会自定义模板。
# 1.5 监控设施的实现方式
# 1.5.1 系统命令:最原始,也最不该被丢掉
用 Linux 自带命令了解系统状态,是最 "原始" 的方式。经典如 top 、 vmstat 、 iostat 、 free 、 ss 、 sar 等,能快速看清 CPU、内存、磁盘、网络、进程的情况。
top 尤其经典 ——CPU、内存、负载、进程一目了然。但它有个致命局限:
只适合少量主机、临时性地看一眼。 一百台机器,你不可能挨个
ssh上去敲top。
不过命令行的价值在于排障现场。这里有一个非常容易搞错的细节,必须讲清楚。
# ⭐ 重点: free / top 里,该盯哪个内存数字?
看一个真实例子:一台 8 GB 内存的机器, top 显示 free 只有 1.3 GB。
这是不是意味着内存快满了?不是。
| 字段 | 含义 | 是否是关键指标 |
|---|---|---|
free / 剩余内存 | 完全未被任何用途占用的内存 | ❌ 不是 |
available / 可用内存 | 在不触发 swap 的前提下,能腾出来给应用用的内存 | ✅ 是 |
原因:Linux 会把空闲内存拿去做 page cache(缓存),这部分内存随时可以被回收交给应用使用。所以 free 小是正常的、甚至是健康的 —— 它说明系统没在浪费内存。
结论:判断内存是否吃紧,只看 available 。
对应的使用率算法就是:
比如上面这台机器,总 8 GB、可用 3 GB:
还有一点要顺带看一眼:swap 有没有被用上。swap 大量被使用,通常是内存真的不够了的信号;swap 完全没用,说明内存还撑得住。
🔗 先记住这个细节,到了本课程后面的 PromQL 部分,你会看到它的 "标准答案":
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 70你会发现,理论环节讲的计算逻辑,和最终写出来的查询语句是一一对应的。这就是为什么基础概念不能跳过。
# 1.5.2 开源软件:从 Nagios、Cacti 到 Zabbix、Prometheus
历史上流行过的监控软件不少:
| 软件 | 时代 | 现状 |
|---|---|---|
| Nagios | 早期 | 已基本退出主流 |
| Cacti | 早期 | 以绘图见长,现已少用 |
| Zabbix | 二十余年历史 | 依然主流,传统环境首选,成熟稳定 |
| Prometheus | 云原生时代 | 容器 / 微服务 / K8s 场景的事实标准 |
必学结论:把 Zabbix 和 Prometheus 这两套吃透,其余可以暂时不看。
# 国产之光:夜莺(Nightingale)
值得一提的还有国人开源的 夜莺(Nightingale),由滴滴团队主导,从早期的 Open-Falcon(猎鹰) 演进而来,现已完全开源免费,不少公司在用。
它的特点:
- 中文文档、中文界面,对国内团队极其友好;
- 产品完整度高,把采集、存储、展示、告警尽量一体化,不像 Prometheus 那样需要东拼西凑一堆组件;
- 兼容 Prometheus 生态,可以直接替代 Prometheus 承担部分职责;
- 官方甚至专门做了 "夜莺 vs Prometheus" 的对比文档。
这门课我们学的仍然是 Prometheus—— 它是业界最主流、最 "标准" 的方案,也是所有面试的默认话题。夜莺可以作为你工作后的备选方案,也可以作为面试里 "我还了解国产方案" 的加分项。
# 1.5.3 监控平台:公有云自带
如果你用的是公有云,根本不用自己部署监控系统:
- 华为云 → 云监控服务
- 阿里云 → 云监控(CloudMonitor)
- 腾讯云 → 云监控
开箱即用,能直接监控云主机、云数据库、负载均衡等云资源。
但要清楚它的边界:云监控擅长 "云资源本身",一旦涉及你自建的中间件、业务指标、容器内部状态,往往还是得自己上 Prometheus。
"云上监控" 与 "自建监控" 也不是替代关系,而是叠加关系。
# 1.6 时序数据库:Prometheus 的性能底座
# 1.6.1 什么是时间序列数据
时间序列数据(Time Series Data):按照时间顺序记录系统、设备状态变化的数据 —— 以时间为横坐标,数据为纵坐标。
它在我们身边无处不在:主机 CPU 每秒一个采样点、智能电表每 15 分钟一个读数、股票每分钟一个价格…… 都是时间序列。
时间序列数据库(TSDB) 则是一种高性能、低成本、稳定可靠的在线时序数据服务,提供高效读写、高压缩比存储、时序数据插值及聚合计算等能力。
典型应用场景:
- 物联网(IoT):海量设备状态数据与业务消息,用于设备监控、业务分析预测、故障诊断;
- 工业 / 能源:电力、化工、制造行业的实时设备状态检测、故障发现、趋势分析(EMS 能源管理系统、生产安全监控系统、电力检测系统);
- 系统运维与业务实时监控:大规模应用集群与机房设备监控,关注资源利用率与业务趋势,实现数据化运营与自动化运维。
# 1.6.2 时间序列数据的五个特点
| 特点 | 含义 | 对设计的启示 |
|---|---|---|
| 写多改少 | 绝大多数是顺序追加写入,几乎不修改 | 可极端优化写入路径,无需复杂事务 |
| 删除成段 | 通常删除一整段时间的数据(如保留 15 天) | 按时间段分块存储,整块删除即可 |
| 读有序 | 查询基本是升序或降序扫描 | 按时间做索引,顺序读 |
| 压缩高效 | 单点平均存储降至 1~2 字节,可节省约 90% 空间 | 专用压缩算法,同时加快写入 |
| 性能高 | 每秒百万级数据点写入;亿级数据点聚合结果秒级返回 | 面向列式 / 块式存储,而非通用行存 |
# 1.6.3 和关系型数据库比,到底强在哪
| 维度 | 关系型数据库(MySQL) | 时序数据库(TSDB) |
|---|---|---|
| 通用性 | 高,什么数据都能塞 | 只擅长时序数据 |
| 监控场景性能 | 一般 | 极高(百万级写入 / 秒) |
| 压缩率 | 一般 | 高(节省约 90% 空间) |
| 数据模型 | 表 / 行 / 主外键 / 强关联 | 度量 + 标签 + 时间戳,结构极简 |
| 典型使用者 | Zabbix | Prometheus、InfluxDB、VictoriaMetrics、TDengine |
一句话记住:关系型数据库追求 "通用",时序数据库追求 "在时间这个维度上极致"。
这也是为什么在大规模容器化监控场景中,用 Prometheus 替代 Zabbix,性能表现会有明显提升。
# 1.7 Prometheus 其人其名
# 1.7.1 名字的由来
Prometheus(普罗米修斯) 是希腊神话中的一位神祇:他从太阳神阿波罗那里盗走火种送给人类,给人类带来了光明,因此成为一位受人敬仰的神。
有意思的是,几乎每个文明都有类似 "为人类带来光明" 的传说(中国的燧人氏钻木取火、盘古开天、女娲造人……)。给一个监控系统起这个名字,寓意大约是:它在黑暗中为你点亮火光,让你看见系统的真实状态。
# 1.7.2 它到底是什么
准确地说:
Prometheus 是一款时序(time series)数据库(TSDB),同时也是一款用于实现 "基于目标(Target)" 的监控系统的关键组件。
它加上 Alertmanager、Pushgateway、Grafana 等外围组件,才构成一套完整的监控系统。
# 1.7.3 发展简史
| 时间 | 事件 |
|---|---|
| 灵感来源 | Google 内部的 BorgMon 监控系统(可理解为 BorgMon 的开源精神后继者) |
| 2012 | 由 SoundCloud 的前 Google 员工创建,作为社区开源项目开发 |
| 2015 | 正式对外发布 |
| 2016 | 加入 CNCF(云原生计算基金会),成为继 Kubernetes 之后第二个由 CNCF 托管的项目 |
| 其后 | 从 CNCF 毕业(Graduated),成为成熟项目 |
技术栈:完全由 Go 语言开发,编译后是单一静态二进制文件,无需任何运行时依赖,部署极为简单。
- 官网:https://prometheus.io/
- 文档:https://prometheus.io/docs/introduction/overview/
- GitHub:https://github.com/prometheus
- CNCF 全景图:https://landscape.cncf.io/
💡 顺带一提:CNCF 现在成员极多,分类也细(应用定义与镜像构建、数据库、可观测性……)。MySQL、Redis、PostgreSQL、Zabbix、Prometheus、Jenkins 都在其中。业界有句玩笑话:"不加入 CNCF,就显得有点落伍了。" 这从侧面说明 Prometheus 不是孤立的工具,而是整个云原生生态的一环。
# 1.8 Prometheus 的核心特点与不足
# 1.8.1 核心特点
| 特点 | 说明 |
|---|---|
| 多维数据模型 | 时间序列由 "度量名 + 键值对标签" 组成,维度极其灵活 |
| 内置 TSDB | 自带时序数据库,无需外部依赖,单机即可完整运行 |
| PromQL | 功能强大的查询语言,支持复杂查询与聚合,是图表与告警的基础 |
| HTTP Pull 采集 | 主动向目标拉取指标,而非被动等待推送 |
| Pushgateway | 为瞬时 / 短周期任务提供 "推" 的补充通道 |
| 目标发现(Service Discovery) | 支持静态配置与自动发现(文件、DNS、Consul、K8s 等) |
| 丰富可视化 | 通过第三方 Dashboard(Grafana)实现 |
| 丰富的 Exporter 生态 | 几乎每种中间件都有现成的采集器 |
# 1.8.2 数据层面的特点
- 监控指标采用 Prometheus 自有的文本格式("Prometheus 格式"),在监控领域极其常见;
- 数据标签支持多维标签,每个独立的标签组合都代表一个独立的时间序列;
- 数据处理内置多种聚合、切割、切片能力;
- 数据存储以双精度浮点型(float64)存储样本值。
🔍 严谨补充:Prometheus 原生样本值只有
float64一种类型;字符串只出现在# HELP之类的元数据里。很多资料写 "支持浮点型和字符串存储",容易让人误以为可以存文本指标 —— 实际不行。存文本明细那是日志系统(ELK/Loki)的活。
# 1.8.3 适用场景
- 记录任何纯数字的时间序列;
- 既适合以机器为中心的监控(主机、中间件),也适合高度动态的面向服务体系结构(微服务);
- 在微服务世界中,对多维数据收集与查询的支持是它的特别优势。
Prometheus 的设计以可靠性为第一优先级,定位是 " 故障期间要用的系统 ":
每个 Prometheus Server 都是独立的,不依赖网络存储或其他远程服务。当基础设施的其他部分崩了,你依然可以依靠它 —— 而且不需要预先搭建庞大的基础设施就能用起来。
但要注意代价:
如果你需要 100% 的准确性,Prometheus 不是好选择。 因为它采集的数据可能不够详细、不够完整(会丢点、会采样)。
正确做法:计费、审计这类要求绝对精确的场景,用专门的系统;Prometheus 负责其余的监控。
# 1.8.4 Prometheus 的四个不足
| 不足 | 说明 | 应对思路 |
|---|---|---|
| 不支持集群化 | 原生单机,无内置 HA 集群方案 | 双机 "跑两份相同配置" + 联邦(Federation);或使用 Thanos / VictoriaMetrics |
| 规模过大时有性能瓶颈 | 单机承载的目标数、序列数有天花板 | 分片、联邦、远程存储 |
| 中文支持不好 | 界面默认英文 | 配合 Grafana 做中文化面板 |
| 功能不完整 | 无原生图形界面、无原生告警发送能力 | 必须配合 Grafana + Alertmanager |
⚠️ 对比一下:Zabbix 是自带图形界面的,所以 "要装 Grafana" 这件事,从 Zabbix 转过来的同学一开始会觉得别扭。
另外补充一个资深运维才知道的八卦:Zabbix 中文界面乱码问题存在二十年了,官方为什么不修? 不是技术问题,是字体版权问题 —— 它不能内置有版权的商业字体,只能由用户自己把系统中的中文字体拷过去配置。类似的 "历史遗留问题",往往都不是技术原因,理解这一点能让你少走很多弯路。
# 1.9 Pull 与 Push:两种数据获取模型
# 1.9.1 Prometheus 的选择:只拉不推
这是 Prometheus 与其它 TSDB 相比最典型的一个特性:
Prometheus 主动从各个 Target 上 "拉取(Pull)" 数据,而不是等待被监控端 "推送(Push)"。
对应到 Zabbix 的语境里,它相当于 Zabbix 的被动模式。
# 1.9.2 先把 Zabbix 的推拉搞清楚
这是最容易被讲混的地方,我们用 "谁主动" 来判断,一秒钟分清:
| 模式 | 谁主动 | 动作方向 | 对 Zabbix Server 的影响 |
|---|---|---|---|
| 被动模式(默认) | Server 主动 | Server → Agent 索要数据 | Server 要挨个问 100 台机器 = 100 次请求,负担重 |
| 主动模式 | Agent 主动 | Agent → Server 推送数据 | Server 只等着接收,负担轻,性能更好 |
所以 Zabbix 的性能优化手段之一,就是把被动模式改成主动模式:让 Agent 主动把数据推给 Server。
🧠 记忆技巧:不要记 "推 / 拉" 这两个字,记 **"谁是主动方"**。
- Zabbix 被动模式 = Server 主动拉 = 对应 Prometheus 的做法
- Zabbix 主动模式 = Agent 主动推 = 对应 InfluxDB 的做法
# 1.9.3 三种系统的对照
| 系统 | 采集模型 | 对应 Zabbix 的说法 |
|---|---|---|
| Zabbix | 推、拉都支持 | 主动模式 + 被动模式 |
| Prometheus | 只支持拉(Pull) | 仅相当于被动模式 |
| InfluxDB | 推(Push) | 相当于主动模式 |
Prometheus 只支持 Pull,不支持 Push。这一点务必记住。
# 1.9.4 Pull 模型为什么是 "优点" 而不是 "缺点"
表面上看,Pull 很吃亏:Server 要主动去问每一台机器,理论上性能不如被推。但 Prometheus 为什么坚持这么做?
| Pull 的优势 | 解释 |
|---|---|
| 集中控制 | 抓什么目标、按什么频率抓、抓哪些指标,全部集中在 Server 端配置,无需改动被监控端 |
| 健康状态天然可知 | 抓不到 = 目标挂了。Prometheus 会自动生成 up 指标,探活是免费的 |
| 调试极其方便 | 浏览器直接打开 http://目标:端口/metrics 就能看到全部指标,不依赖任何推送服务 |
| 目标可控可审计 | Server 端就是唯一事实来源,不会出现 "谁偷偷推了脏数据" |
| 契合动态环境 | 配合服务发现,目标增删自动跟上,无需在每个容器里配推送地址 |
Pull 的核心目标:Prometheus 的根本目标是收集 Target 上已经预先完成聚合的聚合型数据,而不是做一个由事件驱动的存储系统。
换句话说:指标该在哪儿算好,就在哪儿算好;Prometheus 只负责 "取走成品"。
关于 "性能不如推" 的担忧:理论上有影响,但 Prometheus 用的是 "专为监控优化的 TSDB",而不是 MySQL 这种通用关系库,实际差距远没有想象中大。
🎯 面试直达:Zabbix 与 Prometheus 有什么区别?
按下面五点作答,条理清晰、直接给分:
- 采集模型:Zabbix 推拉都支持(默认被动 = 拉,可改主动 = 推);Prometheus 只支持 Pull。
- 存储:Zabbix 依赖关系型数据库(MySQL);Prometheus 内置时序数据库 TSDB。
- 数据模型:Zabbix 以主机 / 监控项为中心;Prometheus 是多维标签模型,
metric + labels唯一确定一条时间序列。- 动态环境适配:Prometheus 原生服务发现,天然适配容器 / K8s;Zabbix 靠 Agent 固定部署,容器场景笨重。
- 生态定位:Prometheus 无图形、无告警发送能力,需配 Grafana + Alertmanager;Zabbix 开箱即用、功能完整。
再加一句收尾:" 两者不是替代关系,很多公司同时使用 "—— 这一句往往就是面试官想听到的深度。
# 1.10 Prometheus 架构
# 1.10.1 整体架构图
flowchart LR | |
SD["服务发现<br/>文件 / DNS / Consul / K8s"] | |
subgraph TARGETS["被监控目标(Target)"] | |
E1["Exporters<br/>node_exporter<br/>mysqld_exporter ..."] | |
E2["Instrumentation<br/>应用内嵌客户端库"] | |
PG["Pushgateway<br/>短周期 / 批处理任务"] | |
PS2["其它 Prometheus<br/>联邦 / 级联"] | |
end | |
PS["Prometheus Server<br/>① Retrieval 抓取<br/>② TSDB 本地存储<br/>③ Rules 规则计算"] | |
AM["Alertmanager<br/>去重 · 分组 · 抑制 · 路由"] | |
R["告警接收方<br/>邮件 / 钉钉 / 企业微信 / Webhook"] | |
G["Grafana / Web UI<br/>可视化"] | |
API["HTTP API<br/>供外部集成"] | |
SD --> PS | |
E1 -->|Pull| PS | |
E2 -->|Pull| PS | |
PG -->|Pull| PS | |
PS2 -->|Pull| PS | |
PS -->|Push Alerts| AM | |
AM --> R | |
PS --> G | |
PS --> API |
# 1.10.2 组件职责速查表
| 组件 | 职责 |
|---|---|
| Prometheus Server | 核心。彼此独立运行,仅依靠本地存储实现核心功能:抓取时序数据、规则处理、生成告警 |
| Client Library(客户端库) | 嵌入到被监控服务中,直接生成并暴露符合 Prometheus 规范的 metrics。Server 来 pull 时直接返回实时状态 |
| Exporters | 部署在第三方软件主机上,把本身不支持 Prometheus 的服务的指标,转换 / 聚合为 Prometheus 格式并暴露出来 |
| Pushgateway | 接收短周期任务主动推送的指标,再由 Server 拉取。弥补 Pull 模型无法采集 "转瞬即逝" 任务的短板 |
| Alertmanager | 接收 Server 的告警,做去重、分组、路由,再高效地发送给接收方 |
| Data Visualization | Prometheus 自带 Web UI + Grafana 等第三方方案 |
| Service Discovery | 动态发现待监控的 Target,容器化环境中尤为关键;该能力目前由 Server 内建支持 |
📌 几乎所有组件都用 Go 编写,因此都极易构建、部署为静态二进制文件。这也是整个生态 "一个 tar 包解压就能跑" 的原因。
# 1.10.3 三种 "数据进入口" 怎么选
Prometheus 默认支持三种从目标获取指标数据的途径,新手最容易在这里选错:
| 方式 | 适用对象 | 说明 |
|---|---|---|
| Instrumentation | 新应用(自己能改代码) | 在代码里引入客户端库(Go / Java / Python…)埋点并暴露 HTTP 端点。最 "原生" 的方式 |
| Exporters | 老应用 / 第三方软件(改不了代码) | 如 MySQL、Redis、Nginx、HAProxy,用官方或社区的 exporter 去抓它们的原始指标并转换格式 |
| Pushgateway | 短周期任务 / 批处理 | 任务运行时间极短,Server 还没来 pull 它就已经退出了,所以只能 "先推到一个中转站",Server 再从中转站 pull |
选型口诀:
能改代码 → Instrumentation
不能改代码,但它一直活着 → Exporter
活得太短,来不及被拉 → Pushgateway
⚠️ 关于 Pushgateway 的两个重要提醒:
- 它只是 Pull 模型的补充,不是让你把 Prometheus 用成 Push 系统;
- 它不做过期清理 —— 推上去的指标会一直存在。所以不要用它来上报 "长期运行服务" 的指标(服务挂了,旧数据还在,会造成 "假存活")。官方明确建议:机器层面、服务层面的常规指标用 Exporter,不要用 Pushgateway。
# 1.10.4 工作流程:四步走
sequenceDiagram | |
participant SD as 服务发现 | |
participant PS as Prometheus Server | |
participant T as Target / Exporter | |
participant AM as Alertmanager | |
participant V as Grafana | |
SD->>PS: 告知当前有哪些目标 | |
loop 每个 scrape_interval | |
PS->>T: GET /metrics (Pull) | |
T-->>PS: 返回文本格式指标 | |
PS->>PS: 写入 TSDB(内存 + WAL + Block) | |
PS->>PS: 按告警规则周期性计算 | |
end | |
PS->>AM: 推送触发的告警 | |
AM->>AM: 去重 / 分组 / 抑制 / 路由 | |
AM-->>AM: 发送到邮件、钉钉等 | |
V->>PS: PromQL 查询 | |
PS-->>V: 返回时序数据 |
用文字再复述一遍,这四步能背下来最好:
- 抓取:Prometheus Server 定期从配置好的 Jobs / Exporters 中拉取(Pull) Metrics;也会拉取 Pushgateway 上的指标(其数据是其他节点 Push 上来的);也可以从其它 Prometheus Server 拉取(联邦)。
- 存储与规则计算:Server 将采集到的指标存到本地 TSDB,并周期性运行已定义的 Alert Rules;产生新序列或触发告警时,向 Alertmanager 推送告警。(每个 Server 独立运行、本地存储,因此天然具备一定程度的冗余能力)
- 告警分发:Alertmanager 依据配置对告警做去重、分组,按 ** 路由(route)** 规则发送到对应接收方。
- 可视化:集成 Grafana 或其他 API 作为图形界面,展示采集到的数据。
# 1.10.5 "Prometheus 只做一件事"
这一点必须建立正确的认知,否则你会一直困惑 "为什么还缺这缺那":
Prometheus 只负责 "时序型指标数据" 的采集与存储。
数据的分析、聚合、直观展示、告警发送,都不由 Prometheus Server 负责,必须配合其它组件完成。
| 我要的功能 | 谁来做 |
|---|---|
| 抓取指标 | Prometheus Server |
| 存指标 | Prometheus Server(内置 TSDB) |
| 查询 / 聚合 | PromQL(Server 内建) |
| 画图 | Grafana |
| 发告警 | Alertmanager |
| 采集各类中间件 | Exporters(官方 + 社区,生态极丰富) |
Exporter 清单见:https://prometheus.io/docs/instrumenting/exporters/
# 1.11 Prometheus 数据模型
# 1.11.1 一切皆为时间序列
Prometheus 中存储的数据,全部是时间序列 —— 即基于同一度量标准、或同一时间维度的数据流。
除了正常存储原始时间序列,Prometheus 还会基于原始数据临时生成新的时间序列(例如 PromQL 的聚合结果),作为后续查询的依据或结果。
核心公式,请务必刻在脑子里:
其中,metric 名称 + 标签集合共同构成这条序列的唯一标识。
💡 关键推论:只要任意一个标签的值变了(包括新增或删除标签),就产生了一条全新的时间序列。
这就是为什么 "标签设计" 在 Prometheus 里如此重要 —— 标签设计不当会导致序列爆炸(cardinality explosion),直接把内存打满。这是第七章 "标签管理" 的核心话题。
# 1.11.2 Metric 名称
- 必须有意义,用于表示 metric 的一般性功能,例如
http_requests_total表示 HTTP 请求总数(_total后缀是 Counter 类型的约定); - 命名规范:由 ASCII 字母、数字、下划线、冒号 组成。
准确的合法字符集(正则):
# metric 名称 | |
[a-zA-Z_:][a-zA-Z0-9_:]* | |
# 标签名称 | |
[a-zA-Z_][a-zA-Z0-9_]* |
⚠️ 常见误区纠偏:不少课件把这条正则简写成
a-zA-Z_:*,看着像 "允许出现星号",实际是笔误。记住上表两条规则即可 —— 首字符不能是数字,metric 名允许冒号,标签名不允许冒号。
关于冒号的保留说明:
冒号(
:)是为用户定义的记录规则(recording rule)保留的,不要用在普通的 exporter 指标名里。
# 1.11.3 标签(Label)
标签以键值对形式存在,用于表示时间序列的不同维度。
基本格式:
<metric name>{<label name>=<label value>, ...}
示例:
http_requests_total{method="POST", endpoint="/api/tracks"}
解读:
http_requests_total{method="POST"}—— 所有 HTTP 请求中的 POST 请求;- 加上
endpoint="/api/tracks"—— 这些请求的 URL 是/api/tracks; - 如果
method="GET",那它就是另一条完全不同的时间序列。
标签的命名与取值规则:
| 规则 | 说明 |
|---|---|
| 键名合法字符 | ASCII 字母、数字、下划线,正则 [a-zA-Z_][a-zA-Z0-9_]* |
__ 开头 | 保留给内部使用,用户不要使用(如 __name__ 是 metric 名的内部表示) |
| 标签值 | 可以是任意 Unicode 字符(可以写中文) |
| 空标签值 | 被认为等同于标签不存在(等价于没有这个标签) |
查询语言(PromQL)正是基于这些维度进行过滤与聚合的 —— 这是 Prometheus 强大灵活性的根源:
# 按 method 维度过滤 | |
http_requests_total{method="POST"} | |
# 按 method 维度聚合 | |
sum by (method) (rate(http_requests_total[5m])) |
# 1.11.4 数据格式(Exposition Format)
Exporter 把采集到的数据转换为纯文本格式,通过 HTTP 响应返回给 Prometheus Server。
格式规则:
- 以 ** 行(
\n)** 为单位,空行被忽略,最后一行为空行; - 文本内容分四类:
| 行首标记 | 含义 |
|---|---|
# HELP | metric 的帮助说明(人类可读描述) |
# TYPE | 声明 metric 类型: counter / gauge / histogram / summary / untyped |
# 开头(其他) | 一般注释,供人阅读,Prometheus 会忽略 |
| 其他行 | 真正的样本数据: 指标名{标签} 值 [时间戳] |
一个真实的 /metrics 输出片段:
# HELP node_cpu_seconds_total Seconds the CPUs spent in each mode. | |
# TYPE node_cpu_seconds_total counter | |
node_cpu_seconds_total{cpu="0",mode="idle"} 1.2345678e+06 | |
node_cpu_seconds_total{cpu="0",mode="system"} 34567.89 | |
# HELP node_load1 1m load average. | |
# TYPE node_load1 gauge | |
node_load1 0.52 |
四种核心数据类型速览(第 2 章会详细展开):
| 类型 | 特征 | 典型例子 |
|---|---|---|
| Counter | 只增不减(除非重置)的累计值 | http_requests_total 、 node_cpu_seconds_total |
| Gauge | 可增可减的瞬时值 | node_load1 、 node_memory_MemAvailable_bytes |
| Histogram | 按桶(bucket)统计分布,可算分位数 | http_request_duration_seconds_bucket |
| Summary | 客户端直接计算分位数 | rpc_duration_seconds{quantile="0.99"} |
# 1.11.5 Job(任务)与 Instance(实例)
这两个词在配置文件、PromQL、Grafana 面板里到处出现,必须分清。
| 概念 | 定义 |
|---|---|
| Instance(实例) | 一个单独的 scrape 目标,通常写作 IP:PORT ,对应单个应用的进程 |
| Job(任务) | 一组同种类型的 instances 集合,主要用于保证可扩展性与可靠性 |
官方式的例子:一个 API 服务 job 包含四个 instances:
job: api-server
├── instance 1: 1.2.3.4:5670
├── instance 2: 1.2.3.4:5671
├── instance 3: 5.6.7.8:5670
└── instance 4: 5.6.7.8:5671
🧠 类比:
job是 " 一个部门的岗位名称 ",instance是 " 这个岗位上具体的人 "。一个岗位可以有多个人轮值(多副本),这就是可扩展性;某个人请假了别人还在(副本冗余),这就是可靠性。
自动生成的内置指标:Prometheus 在每次抓取后,会为目标自动生成一组带 job 和 instance 标签的元指标。这些指标不需要你在目标上暴露,是 "白送" 的运维利器:
| 指标 | 含义 | 典型用途 |
|---|---|---|
up{job,instance} | 目标是否健康:1 正常,0 不正常 | 最常用的存活告警: up == 0 |
scrape_duration_seconds{job,instance} | 本次抓取耗时 | 发现抓取缓慢的目标 |
scrape_samples_scraped{job,instance} | 本次抓取到的样本数量 | 监控指标量是否异常膨胀 |
scrape_samples_post_metric_relabeling{job,instance} | relabel 之后剩余的样本数 | 验证 relabel 规则效果 |
scrape_series_added{job,instance} | 本次抓取新增的序列数(约数) | 发现序列爆炸的早期信号 |
💡 实战价值:
scrape_series_added突然飙升,往往意味着某个应用偷偷加了高基数标签,或者发生了一次重启导致新序列涌入。提前发现,能救你一命。
# 1.11.6 本节小结
数据模型:metric 名称 + 标签(= 唯一时间序列)
数据类型:Counter / Gauge / Histogram / Summary(+ untyped)
组织结构:多个 instances 组成一个 job
命名规则:名称 [a-zA-Z_:][a-zA-Z0-9_:]* | 标签 [a-zA-Z_][a-zA-Z0-9_]*
# 1.12 Prometheus 数据处理四部曲
# 1.12.1 数据获取:一切基于 HTTP
Prometheus 采集指标数据的方式,本质上是 HTTP Call:从目标配置文件中指定的网络端点(endpoint,即 IP:Port ,代表一个应用)上周期性获取指标。一个端点上通常不止一个指标,而是成百上千个。
这里有一个根本性约束,必须理解:
Prometheus 的所有指标都必须以 HTTP 方式暴露出来。
因此 Prometheus 无法直接获取内核数据、硬件数据 —— 它只能通过其它机制间接获得(例如
node_exporter读取/proc后再转换为 HTTP 端点暴露)。
这就是为什么 "安装一个 exporter" 几乎是所有监控任务的起点。
# 1.12.2 数据存储:本地 TSDB 的分层结构
Prometheus 采用自定义格式将时间序列存储在本地磁盘上,结构相当精妙:
- 本地 TSDB 以每 2 小时为间隔切分为一个 Block;
- 每个 Block 内部又分为多个 Chunk 文件;
- Chunk 是存储的基本单位,用来存放采集到的时序数据(包括元数据 metadata);
- index 索引文件:对 metrics(对应一次 KV 采集数据)和 labels(标签)建立索引后存储在 Block 中。
写入路径与 WAL 保护机制:
Prometheus 平时把采集到的数据先都放在内存里,以类似缓存的方式加快搜索和访问;
同时通过 WAL(Write-Ahead Logging,预写日志) 把数据落盘到wal目录;
当进程崩溃或宕机重启时,依靠 WAL 恢复数据并重新加载到内存。
真实的 data 目录长这样:
/usr/local/prometheus/data | |
├── 01G9RSD61ZEF16T5YGE91K49MZ/ ← 一个 Block(约 2 小时的数据) | |
│ ├── chunks/ ← 压缩后的样本数据 | |
│ │ └── 000001 | |
│ ├── index ← 标签与序列的索引 | |
│ ├── meta.json ← 该 Block 的元信息(时间范围、样本数等) | |
│ └── tombstones ← 删除标记(软删除) | |
├── 01G9RZ8VXF2FHHB18CW0594P8T/ | |
│ ├── chunks/000001 | |
│ ├── index | |
│ ├── meta.json | |
│ └── tombstones | |
├── chunks_head/ ← ┐ | |
│ ├── 000002 │ 当前正在写入的"头部块" | |
│ └── 000003 ← ┘ | |
├── lock ← 进程锁,防止多实例共用目录 | |
├── queries.active ← 正在执行的查询 | |
└── wal/ ← 预写日志,宕机恢复用 | |
├── 00000000 | |
├── 00000001 | |
└── 00000002 |
⚠️ 生产提醒:
- 数据目录不要放在共享存储上(NFS 会破坏
lock与 WAL 语义);- 不要用
rm直接删 Block 目录,用官方 API 或配置保留策略;- 磁盘最好是 SSD,TSDB 对随机 IO 敏感。
# 1.12.3 数据分析:PromQL
Prometheus 提供了专门的查询语言 PromQL(Prometheus Query Language),支持实时查询与聚合运算,是图表展示与告警规则的共同基础。
PromQL 处理两种核心向量:
| 向量类型 | 含义 | 直观理解 |
|---|---|---|
| 即时向量(Instant Vector) | 最近一次抓取的单个时间戳上的一组数据 | 一个时间点的数据 |
| 范围向量(Range Vector) | 指定时间范围内的所有时间戳上的数据 | 一个时间段的数据 |
# 即时向量:此刻的 CPU 空闲时间总量 | |
node_cpu_seconds_total{mode="idle"} | |
# 范围向量:过去 5 分钟的所有采样点(注意 [5m]) | |
node_cpu_seconds_total{mode="idle"}[5m] |
两者最直观的区别:范围向量不能直接画成折线图,必须先经过
rate()、avg_over_time()这类函数 "降维" 成即时向量才行。这是新手最常踩的坑之一。
PromQL 同时内置了大量处理函数(数学运算、聚合、时间函数、 rate / increase 、 histogram_quantile 等),第 5~6 章会逐一展开。
# 1.12.4 数据告警:职责分离的设计
Prometheus 的告警是一条明确分权的链路:
Prometheus Server Alertmanager
───────────────── ─────────────
按告警规则周期性计算 ──告警指示──► 去重 → 分组 → 抑制 → 路由
(只负责"发现问题") (只负责"通知谁")
- 告警指示由 Prometheus Server 基于用户提供的
alerting rules周期性计算生成; - Alertmanager 接收到告警指示后,基于用户定义的告警路由(route),向告警接收人发送告警信息。
💡 为什么这样设计? 因为 "判断异常" 和 "决定通知" 是两件完全不同的事。前者是时序计算(Prometheus 擅长),后者是消息治理(去重、静默、值班表、升级策略 ——Alertmanager 擅长)。拆开之后,两边都能做得更好,也让 Prometheus 保持了 "单一职责"。
# 1.13 本章小结
mindmap | |
root(("Prometheus<br/>入门")) | |
可观测性 | |
指标 Metrics | |
日志 Logging | |
追踪 Tracing | |
六大环节 | |
数据来源 | |
数据采集 | |
数据存储 TSDB | |
数据处理 | |
数据展示 | |
数据告警 | |
监控方法 | |
四个黄金指标 | |
延迟 流量 错误 饱和度 | |
存储 | |
时序数据五特点 | |
压缩 90% | |
百万级写入 | |
架构 | |
Server 核心 | |
Exporters | |
Pushgateway | |
Alertmanager | |
Grafana | |
Service Discovery | |
Pull 模型 | |
只拉不推 | |
集中控制 | |
up 免费探活 | |
数据模型 | |
metric 名 + 标签 | |
四种类型 | |
job / instance |
必须带走的一句话:
Prometheus 是一套 " 以 Pull 方式采集、用多维标签建模、把数据存进内置 TSDB、靠 PromQL 分析、由 Grafana 展示、交给 Alertmanager 告警 " 的监控组件集合。
它只做 "指标" 这一支柱,也只做 "采集 + 存储 + 查询" 这三件事 —— 其它都得靠生态补齐,而这恰恰是它最强大的地方。
# 1.14 面试高频问答
Q1:你们公司为什么同时用 Zabbix 和 Prometheus?
因为两者定位不同。Zabbix 擅长传统固定资产和网络设备监控(SNMP/IPMI 生态完善、开箱即用),Prometheus 擅长容器化、动态变化的微服务环境(服务发现 + 多维标签)。老业务用 Zabbix,容器平台用 Prometheus,是很常见的组合。
Q2:Prometheus 的采集模型是什么?和 Zabbix 有什么不同?
Prometheus 只支持 Pull,相当于 Zabbix 的被动模式;Zabbix 推拉都支持(默认被动,可改主动)。InfluxDB 则是 Push。
Pull 的好处是配置集中在 Server 端、up指标免费探活、调试方便、天然配合服务发现。
Q3:Prometheus 为什么性能好?
核心是存储:它用的是自研 TSDB(时序数据库),针对 "写多改少、删除成段、读有序" 的特点做了分块存储和专用压缩,单点平均 1~2 字节,可节省约 90% 空间,支持百万级写入 / 秒、亿级聚合秒级返回;而 Zabbix 用通用关系库,不是为监控场景优化的。
Q4:什么是时间序列?唯一标识是什么?
时间序列是按时间顺序记录的、同一度量维度的数据流。唯一标识是 metric 名称 + 一组标签。任何一个标签值变化(新增或删除标签),都会产生一条新的时间序列。
Q5:Prometheus 有哪些不足?怎么弥补?
① 不支持集群(用双机 + 联邦,或 Thanos/VictoriaMetrics);② 规模过大有瓶颈(分片、联邦、远程存储);③ 中文支持差(Grafana 面板中文化);④ 功能不完整(配 Grafana + Alertmanager)。
Q6: up 指标是干什么的?
Prometheus 每次抓取后自动生成的元指标,
1表示目标健康、0表示抓取失败。最经典的存活告警就是up == 0。
# 1.15 动手练习
# 练习 1(观察题) 亲手看一眼 /metrics
准备一台 Linux 机器(或虚拟机),下载 node_exporter 并运行,然后:
# 终端 1:启动 exporter(默认端口 9100) | |
./node_exporter | |
# 终端 2:查看原始指标输出 | |
curl -s http://localhost:9100/metrics | head -50 | |
# 找出所有 HELP/TYPE 声明 | |
curl -s http://localhost:9100/metrics | grep -E '^# (HELP|TYPE)' | head -20 | |
# 找出内存相关指标 | |
curl -s http://localhost:9100/metrics | grep node_memory_Mem |
要回答的问题:
node_memory_MemTotal_bytes是什么类型?(Counter 还是 Gauge?为什么?)node_cpu_seconds_total是 Counter,那你怎么算出 "当前 CPU 使用率"?只用一次抓取的值能算出来吗?- 用本章的内存公式,算出你这台机器当前的内存使用率。
# 练习 2(思考题) Pull 还是 Push?
以下场景分别该用哪种方式?
| 场景 | 你的答案 |
|---|---|
| Nginx 反向代理(长期运行) | ? |
| 每天凌晨跑 30 秒的备份脚本,要记录耗时与退出码 | ? |
| 你自己用 Go 写的 API 服务 | ? |
| 机房核心交换机 | ? |
参考答案:① Exporter(
nginx_exporter);② Pushgateway;③ Instrumentation(客户端库埋点);④ Exporter(snmp_exporter)。
# 练习 3(设计题) 用四个黄金指标设计监控清单
假设你要监控一个 "用户登录" 接口,请用延迟 / 流量 / 错误 / 饱和度四个维度,各写出至少 2 个具体监控项。
提示:延迟要区分成功与失败;流量可用 QPS;错误可用 HTTP 5xx 率;饱和度可看该服务所依赖的数据库连接池使用率。
# 练习 4(原理题) 为什么 free 小不是问题?
在一台机器上执行 free -h ,观察 free 与 available 两列的差异,并解释:
- 为什么两者差距可能很大?
- 如果
swap开始被大量使用,说明什么? - 用公式算出使用率,并说出对应的告警阈值。
# 1.16 下章预告
本章我们把 Prometheus"是什么、为什么、由什么组成" 讲透了。下一章将正式动手:
- 下载与部署 Prometheus Server
- 读懂
prometheus.yml的每一个字段 - 配置第一个静态 Target
- 在 Web UI 里写出你的第一条 PromQL
- 认识 Counter / Gauge / Histogram / Summary 的本质差异
先把本章的架构图画三遍 —— 后面所有命令和配置,都是在给这张图 "接线"。
