作为一个在技术一线摸爬滚打的开发者,你一定遇到过这样的场景:凌晨两点被报警电话叫醒,因为生产环境的服务突然挂了;或者用户投诉系统卡得没法用,但你登录服务器一看,CPU 和内存利用率却很低,完全不知道瓶颈在哪里。这些问题往往不是发生在瞬间,而是有一个累积的过程。如果我们能拥有一双“慧眼”,实时洞察系统内部的运行状态,在问题变成灾难之前将其扼杀在摇篮里,那该多好?
在这篇文章中,我们将深入探讨现代云原生监控领域的“黄金搭档”——Prometheus 和 Grafana。我们将不仅学习它们是什么,还将通过实战代码和详细配置,手把手教你如何搭建一套企业级的监控可视化系统。无论你是运维工程师、后端开发者,还是对系统稳定性感兴趣的技术爱好者,这篇文章都将为你提供从理论到实践的全面指南。
目录
为什么我们需要 Prometheus 和 Grafana?
在传统的监控体系中,我们往往依赖简单的脚本或老旧的工具(如 Nagios)来检查服务是否“活着”。但在微服务架构和云原生时代,服务之间的调用关系错综复杂,单纯知道“服务是否在线”已经远远不够了。我们需要知道服务运行得有多好,响应时间是多少,错误率随时间如何变化,以及未来的资源消耗趋势。
这就是我们需要将 Prometheus 和 Grafana 结合使用的原因。让我们先来看看它们各自扮演的角色。
初识核心组件:分工明确的黄金搭档
Prometheus:数据收集的“心脏”
Prometheus 是一个开源的监控系统,它最初由 SoundCloud 开发,后来成为了云原生计算基金会(CNCF)的毕业项目。我们可以把它想象成一个专门负责“打捞”数据的强力抽水机。
它的核心工作是从我们的应用程序、服务器中间件(如 Nginx、MySQL)以及基础设施(如 Linux 服务器)中实时抓取指标数据。这些数据不仅仅是“开/关”状态,而是包含了丰富的数值信息,例如每秒处理的请求数、GC 花费的时间或磁盘 I/O 等待时间。Prometheus 会将这些数据以其特有的高效格式存储在其自带的时序数据库中。
Grafana:数据呈现的“面孔”
如果 Prometheus 是存储数据的仓库,那么 Grafana 就是那个精致的橱窗。Grafana 是一个开源的可视化平台,它不仅支持 Prometheus,还能连接 Elasticsearch、InfluxDB 等多种数据源。
Grafana 的强大之处在于它能够将 Prometheus 收集到的那些枯燥的数字,转化为直观的折线图、热力图、饼图和仪表盘。通过 Grafana,我们可以一眼看出系统当前的负载趋势,或者在过去的一小时内哪个服务的错误率突然飙升。简而言之,Prometheus 负责“理解”数据,而 Grafana 帮助我们“看见”数据。
核心概念解析:掌握监控的“通用语言”
要熟练使用这套工具,我们必须先理解它们背后的核心术语。这就像学编程要先学语法一样。
1. 指标
指标是我们想要监控的具体对象。它通常是一个数值,反映了系统在某个特定维度的性能。
- Counter(计数器):只能一直往上涨的数据。比如“服务器启动后处理的总请求数”。它不会减少,只会增加。
- Gauge(仪表):可以上下波动的数据。比如“当前的内存使用量”或“当前的线程数”。它反映了系统的瞬时状态。
实际场景:我们要监控网站的访问量,这是一个 Counter;我们要监控当前的在线人数,这是一个 Gauge。
2. 时间序列数据
这是 Prometheus 存储数据的方式。每一个指标不仅包含数值,还包含一个时间戳。这意味着,当我们查询数据时,我们得到的不仅仅是一个数字,而是一连串随时间变化的点。
例子:http_requests_total{job="api-server"} 不仅仅告诉我们总请求数,还记录了 10:00:01 是 100 次,10:00:02 是 102 次。这种连续性让我们能够画出图表,分析趋势。
3. PromQL (Prometheus Query Language)
这是 Prometheus 自带的查询语言,功能非常强大。它允许我们通过数学运算来处理时序数据。你可能会觉得它有点像 SQL,但它是专门为了时间序列设计的。
实用代码示例 1:计算 QPS(每秒查询率)
假设我们有一个名为 api_http_requests_total 的计数器。直接看这个数字没什么意义,因为它一直累积。我们更关心的是“最近 5 分钟平均每秒有多少请求”。
# 语法解释:rate() 函数用于计算范围向量中时间序列的每秒平均增长率。
# [5m] 表示取过去 5 分钟的数据。
rate(api_http_requests_total[5m])
实用代码示例 2:预测磁盘空间耗尽时间
如果我们想知道以现在的写入速度,硬盘还有多久会满,可以使用 predict_linear 函数。
# 语法解释:predict_linear 基于过去 1 小时的数据,预测未来 4 小时的值。
predict_linear(node_filesystem_avail_bytes[1h], 4*3600) < 0
这条查询语句会在预测值小于 0(即空间耗尽)时触发告警,这就是 PromQL 的威力所在。
4. Exporter(采集器)
Prometheus 采用的是“ Pull 模型”,即它主动去目标拉取数据。但是,并不是所有的应用程序或系统天生就能讲 Prometheus 能听懂的语言。这就需要 Exporter 作为翻译官。
Exporter 是一个运行在目标机器上的小工具,它负责收集特定的指标(比如 Linux 的 CPU 数据,或者 MySQL 的连接数),并将其转换为 Prometheus 可以读取的 HTTP 接口格式。
常用 Exporter 推荐:
- Node Exporter:监控硬件和操作系统的必选工具。
- MySQL Server Exporter:专门抓取数据库的性能指标。
- Blackbox Exporter:用于探测 HTTP、TCP、ICMP 等外部服务的可用性(就像一个拨测机器人)。
5. 告警
监控的最终目的是为了发现问题。Prometheus 允许我们定义规则。一旦指标数据满足了我们设定的条件(例如 CPU > 90% 且持续 5 分钟),Prometheus 就会触发一个告警事件,并将其推送给 Alertmanager,再由 Alertmanager 发送邮件、钉钉或 Slack 通知。
6. 目标
在 Prometheus 的配置文件中,我们需要明确告诉它:“去哪里抓取数据?”这个“哪里”就是目标。通常是一个 IP 加端口的 URL。
实战演练:将 Prometheus 与 Grafana 强强联手
光说不练假把式。让我们通过实战来搭建这套系统。我们将使用 Docker,这是最快捷、最标准化的方式。
第一步:准备环境与安装
首先,我们需要确保你的机器上安装了 Docker 和 Docker Compose。我们将编写一个 docker-compose.yml 文件来同时启动 Prometheus、Grafana 和一个必备的 Node Exporter。
实用代码示例 3:完整的 docker-compose.yml
请复制以下代码并保存为 docker-compose.yml。我已经为你加好了详细的中文注释,解释每一行的作用。
version: ‘3.8‘
services:
# 1. Prometheus 服务
prometheus:
image: prom/prometheus:latest
container_name: prometheus
# 使用挂载卷,这样我们可以在宿主机直接修改配置文件,不需要重启容器
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
# 暴露 9090 端口供浏览器访问
ports:
- "9090:9090"
# 确保 prometheus 依赖网络配置
networks:
- monitoring
# 2. Grafana 服务
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000" # 默认用户名和密码通常是 admin/admin
environment:
# 设置一些环境变量,比如时区
- GF_INSTALL_PLUGINS= # 可以在这里指定需要安装的插件
networks:
- monitoring
depends_on:
- prometheus
# 3. Node Exporter (用于抓取宿主机指标)
node_exporter:
image: prom/node-exporter:latest
container_name: node_exporter
ports:
- "9100:9100"
networks:
- monitoring
# 定义一个网络,让它们可以互相通信
networks:
monitoring:
driver: bridge
在上面的配置中,我们提到了 ./prometheus.yml。我们需要在同级目录下创建这个文件,告诉 Prometheus 去哪里抓取数据。
实用代码示例 4:prometheus.yml 配置文件
# 全局配置
global:
scrape_interval: 15s # 每 15 秒抓取一次数据
evaluation_interval: 15s # 每 15 秒评估一次告警规则
# 告警管理器配置 (这里暂略,重点展示抓取配置)
# alerting:
# ...
# 抓取配置列表
scrape_configs:
# 这个 job 名字叫 ‘prometheus‘,用于监控 Prometheus 自身
- job_name: ‘prometheus‘
static_configs:
# targets 指定了抓取目标,这里用 docker 服务名代替 IP
- targets: [‘localhost:9090‘]
# 这个 job 名字叫 ‘node‘,用于监控我们的 Node Exporter
- job_name: ‘node‘
static_configs:
# node_exporter 是我们在 docker-compose 中定义的服务名
- targets: [‘node_exporter:9100‘]
现在,打开终端,运行 docker-compose up -d,稍等片刻,你的监控核心就已经在后台运行了!
第二步:将 Prometheus 数据接入 Grafana
现在 Prometheus 在抓取数据,Grafana 已经启动,但它们还互不相识。让我们来“连线”。
- 打开浏览器访问
http://localhost:3000。 - 你会看到登录界面。输入默认账号:INLINECODE2a5c8e65,密码:INLINECODEe57f4ee3。系统会提示你修改密码,建议按指引操作。
- 登录后,点击左侧边栏的 “齿轮”图标。
- 选择 Data sources(数据源)。
- 点击 Add data source,选择 Prometheus。
- 在设置页面的 URL 一栏中,填入 Prometheus 的访问地址。因为我们都在同一个 Docker 网络里,这里填:
http://prometheus:9090
(注意:这里填的是 Docker 容器内部的名称,而不是 localhost)
- 滚动到最下方,点击 “Save & Test”。如果看到绿色的提示框“Data source is working”,恭喜你,连接成功!
第三步:可视化第一个指标
数据通了,我们来看看数据长什么样。
- 点击左侧的 “+” 号,选择 Create Dashboard。
- 点击 Add an empty panel。
- 在下方的查询框中,输入我们之前学过的 PromQL 查询语句。尝试输入:
rate(node_cpu_seconds_total{mode="idle"}[5m])
这条查询的意思是:查看 CPU 空闲时间的变化率。注意 Grafana 通常会自动进行单位换算,所以如果反过来用 1 减去这个值,就是 CPU 的使用率。
让我们换个更直观的查询,直接看 CPU 使用率:
# 计算逻辑:100 - 空闲 CPU 时间占比 = 总 CPU 使用率
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
输入这条语句后,上方应该会立刻出现一条波动的曲线图。你可以给它起个名字,比如“服务器 CPU 实时监控”,然后点击右上角的保存。这完全是属于你的第一个监控面板!
进阶技巧:如何从数据中发现价值?
只是画个图还不够。作为专业的技术人员,我们需要关注一些深层次的性能优化建议和常见陷阱。
最佳实践 1:警惕“高基数”陷阱
在定义标签时,我们要非常小心。例如,你可能想给每个用户 ID 或每个请求 URL 都加一个标签。
千万不要这样做。
如果你的标签组合(例如 INLINECODE7b16ceb9 从 1 到 100 万)变化无穷,Prometheus 需要为每一种组合存储一个时间序列。这会导致内存爆炸,查询变慢。最佳实践是只保留高维度的、低基数的标签,比如 INLINECODE45e346b3 (prod/staging)、INLINECODE90e36a8f (api/worker) 或者 INLINECODE3509a47c (500/404)。
最佳实践 2:使用 Recording Rules(预计算规则)
如果你发现一个复杂的 PromQL 查询在 Grafana 中加载得很慢,或者在同一个 Dashboard 被重复计算多次,你应该使用 Recording Rules。
这相当于在 Prometheus 后台预先运行好这些复杂的查询,把结果存成一个新的指标。这样 Grafana 画图时只需要读取这个现成的结果,速度会快得多。
实用代码示例 5:预计算规则配置
创建一个 INLINECODE9a623e5c 文件,并在 INLINECODEdcd35441 中引用它。
groups:
- name: api_rules
interval: 30s
rules:
# 定义一个新指标 job:http_requests:rate5m
# 它的值就是后面复杂的查询结果
- record: job:http_requests:rate5m
expr: sum by (job) (rate(http_requests_total[5m]))
常见问题排查:Grafana 显示“N/A”或断线?
这是新手最常遇到的问题。通常有两个原因:
- 时间范围不匹配:Prometheus 抓取数据是实时的,但你在 Grafana 里选择的时间范围可能是“从明年开始”(显示 N/A)或者“未来 1 小时”。请检查右上角的时间选择器是否选择了“Last 5 minutes”或“Last 1 hour”。
- 查询速率过快:如果你在 INLINECODE15640f39 函数中使用了 INLINECODE6911793a 这样的极短时间窗口,但 Prometheus 每 15 秒才抓取一次,数据可能还没来得及产生计算结果。建议将窗口至少设置为抓取间隔的 4 倍(例如
1m)。
总结与后续步骤
在这篇文章中,我们一起探索了 Prometheus 和 Grafana 的核心概念,理解了它们是如何通过指标、时间序列和 PromQL 紧密协作的。更重要的是,我们通过编写真实的 docker-compose 和配置文件,搭建了一套属于你自己的监控系统。
但这仅仅是开始。为了真正保障系统的稳定性,我建议你接下来尝试:
- 配置告警通知:不要只盯着屏幕,去配置 Alertmanager,让 Critical 级别的告警直接发到你的手机或钉钉机器人。
- 探索丰富的仪表盘:Grafana 官网上有大量社区贡献的现成仪表盘(Import Dashboard 功能)。你可以尝试导入 ID 为
8919的 Node Exporter Full 看看别人是如何做专业监控的。 - 应用埋点:把监控深入到你的业务代码中。记录下“订单创建失败数”、“支付处理耗时”等业务指标,这比 CPU 监控更能反映业务健康度。
希望这篇文章能帮助你建立起对系统监控的直观理解。现在,动手去试试看吧,让你的系统不再“裸奔”!