Metrics、Prometheus、Grafana 三者关系

这三者如何区分、职责分别是什么、为什么总一起出现但又绝不是一回事

Posted by Ekko on May 21, 2026

这篇笔记用于梳理 MetricsPrometheusGrafana 三者的层级关系与职责边界。重点不是分别重复定义,而是建立一套能够直接用于排障、选型与后续学习的整体视图。

它关注的是“数据抽象层、监控系统层、展示协作层”之间如何分工,以及为什么三者经常一起出现却绝不是同一种东西;具体到埋点 API、PromQL 细节、Dashboard 设计方法,则分别放在相关专题中展开。

参考资料:

官方文档:Prometheus Data ModelMetric TypesHistograms and summariesGrafana Data sourcesGrafana DashboardsMicrometer Concepts

站内前文:Metrics 监控数据Prometheus 监控系统Grafana 监控可视化

[TOC]


1. 最短答案

可以压缩成三句话:

  • Metrics 是一种观测数据抽象
  • Prometheus 是一个以 Metrics 为核心的数据采集、存储、查询与告警系统
  • Grafana 是一个把数据源查询结果组织成可视化界面的平台

也就是说:

  • Metrics 是“数据类型 / 观测方式”
  • Prometheus 是“处理这类数据的系统”
  • Grafana 是“把这些数据展示给人的界面层”

这三者经常一起出现,是因为它们刚好组成了一条非常典型的工程链路:

1
2
3
应用产生 Metrics
    -> Prometheus 抓取并存储
    -> Grafana 查询并展示
对象 所属层级 核心职责 不负责什么
Metrics 数据抽象层 把系统状态、事件和分布表达为可聚合的数值时序 不负责采集、存储、查询界面
Prometheus 监控系统层 抓取、存储、查询、聚合与规则评估 不负责多数据源可视化协作
Grafana 展示与协作层 连接数据源、组织查询结果、提供 dashboard 与 Explore 不定义指标语义,也不是时序数据库

2. 为什么很多人会把三者混在一起

因为在日常工作里,经常会同时接触到:

  • 应用暴露 /metrics
  • Prometheus 抓这些 metrics
  • Grafana 把它们画成图

久而久之就容易形成一种错觉:

  • “这不就是一套东西吗”

但这其实是:

  • 三层不同抽象恰好串成了一条常见工具链

这有点像:

  • SQL 是查询语言
  • MySQL 是数据库
  • DataGrip 是客户端

三者有关,但显然不是同一种东西。


3. 先拆开看:Metrics 是抽象,不是产品

Metrics 本质是什么

Metrics 是一种把系统状态、事件和分布压缩成数值时间序列的方式。

它关注的是:

  • 当前状态
  • 变化趋势
  • 聚合统计
  • 告警阈值

典型例子:

  • 请求总数
  • 错误总数
  • 当前连接数
  • 队列长度
  • 请求耗时分布

Metrics 解决什么问题

它擅长回答:

  • 系统整体现在怎么样
  • 趋势有没有异常
  • 某类问题有没有扩大
  • 哪个维度最有问题

它不擅长回答:

  • 某条具体请求的详细过程
  • 某个用户做了什么操作
  • 一段错误日志的完整上下文

Metrics 不是 Prometheus 发明的

这是一个常见误解。

Metrics 这个观测思路早于 Prometheus,也不依赖 Prometheus。

Metrics 完全可以发送到:

  • Prometheus
  • InfluxDB
  • CloudWatch
  • Datadog
  • OpenTelemetry 后端

所以:

  • Metrics 是更上层的概念
  • Prometheus 只是其中一种非常主流的落地系统

4. 再看 Prometheus:它是 Metrics 系统

Prometheus 处理的是 Metrics

Prometheus 围绕 Metrics 做了完整系统化设计,包括:

  • 抓取
  • 存储
  • 查询
  • 聚合
  • 录制规则
  • 报警规则

所以它不是抽象定义,而是:

  • 具体产品 / 具体系统

它和 Metrics 的关系

更直观的类比是:

  • Metrics 是“粮食”
  • Prometheus 是“仓库 + 加工厂 + 计算系统”

也就是说:

  • Metrics 是被处理对象
  • Prometheus 是处理它们的基础设施

为什么不是所有 Metrics 都一定进 Prometheus

因为 Prometheus 有自己的适用边界:

  • 适合数值型时序
  • 核心上围绕 pull 模型构建
  • 适合 label-based data model

如果需求是:

  • 全文检索日志
  • 分布式 trace 分析
  • 海量长期归档

那 Prometheus 就不是唯一答案。


5. 再看 Grafana:它是界面层,不是 Metrics 系统本体

Grafana 不定义 Metrics

Grafana 不负责定义:

  • Counter 是什么
  • Histogram 是什么
  • 标签基数应该怎么控制

这些语义不是 Grafana 创造的。

Grafana 也不天然负责存储 Metrics

Grafana 官方文档明确说明:

  • data source 才是存储后端
  • Grafana 只负责查询这些后端并展示结果

所以如果没有后端数据源:

  • Grafana 自己并不会凭空产生监控数据

不过还需要区分一件事:

  • Grafana 自身会保存用户、dashboard、folder、alert rule、data source 配置等平台元数据
  • 这些元数据存储,不等于 Metrics 时序数据存储

它的职责更像“人机交互层”

Grafana 最核心的价值在于:

  • 把 Prometheus 等后端的查询结果变成 dashboard、panel、variable、Explore、alerting 等人可消费的形式

所以更准确地说:

  • Grafana 是 observability UI / UX 层

Grafana 可以做 Alerting,但层级没有改变

Grafana 新版具备统一告警能力,可以:

  • 基于数据源查询结果定义规则
  • 管理 contact point、notification policy 与告警视图

但这并不改变它的基本定位:

  • 告警查询仍然依赖后端数据源
  • 指标语义与时序存储仍然来自 Prometheus 等系统

6. 三者的层级关系

可以按下面的层级记忆:

第一层:数据抽象层

  • Metrics

回答:

  • 系统要观测的是什么数据形态

第二层:监控系统层

  • Prometheus

回答:

  • 这些 Metrics 怎么采、怎么存、怎么查、怎么算、怎么报警

第三层:展示与协作层

  • Grafana

回答:

  • 人怎么查看、筛选、组合、分享和分析这些结果

所以三者并不是平级替代关系,而是:

  • 上下游协作关系

这三者并不覆盖全部可观测性

这组三件套解决的是可观测性中的一大块,但不是全部。

  • Metrics 更适合看整体状态、趋势和聚合结果
  • Logs 更适合看文本上下文、错误细节和原始事件
  • Traces 更适合看单次请求或跨服务调用路径

因此:

  • Prometheus + Grafana 很常见
  • 但它们本身并不等于完整的 observability stack

7. 一个最常见的真实链路

在 Java / Spring Boot 场景里,一条典型链路通常是:

1
2
3
4
5
6
7
应用代码
    -> Micrometer 记录 Metrics
    -> Spring Boot Actuator 暴露 /actuator/prometheus
    -> Prometheus 周期抓取
    -> Prometheus TSDB 存储
    -> Grafana 配置 Prometheus data source
    -> Dashboard / Explore 查询展示

如果把告警链路也补上,可以得到一张更完整的协作图:

graph LR
    A[应用代码 / Exporter] --> B[Metrics 端点]
    B --> C[Prometheus Server]
    C --> D[PromQL / Recording Rules]
    C --> E[Alerting Rules]
    E --> F[Alertmanager]
    C --> G[Grafana]

如果把它拆开看:

  • Micrometer:应用埋点门面
  • Metrics:暴露出来的数据模型
  • Prometheus:采存算
  • Grafana:展示和探索

这条链路里每一层都有自己的职责,没有谁应该替代谁。


8. 一个高频误区:把 Metrics 当成 Prometheus 语法

很多人学了 CounterGaugeHistogram 之后,会下意识觉得:

  • 这就是 Prometheus 的东西

其实不完全对。

更准确的说法应该是:

  • 这些是 Metrics 世界里的核心类型
  • Prometheus 采用并强化了这套思维

同样地:

  • Micrometer 有 Timer
  • OpenTelemetry Metrics 也有自己的 instrument 语义

所以:

  • Metrics 是更广义抽象
  • Prometheus 是其中一个非常重要的实现生态

9. 一个高频误区:把 Grafana 当成“监控系统”

很多团队平时打开 Grafana 最多,所以会下意识说:

  • “Grafana 监控挂了”

这句话日常沟通没问题,但技术上其实要拆开。

因为一个监控链路里可能出现几种不同故障:

应用没暴露 Metrics

这时问题在:

  • 应用埋点或 exporter

Prometheus 没抓到

这时问题在:

  • target
  • 网络
  • 配置
  • service discovery
  • relabeling

Prometheus 有数据但 Grafana 查错了

这时问题在:

  • panel query
  • variable
  • time range
  • panel transform

Grafana 页面正常,但图为空

这并不说明:

  • Grafana 没数据存储能力不行

更可能是:

  • 后端根本没返回数据

这就是为什么三者一定要拆开理解。


10. 用职责来硬区分

Metrics 的职责

  • 定义观测数据是什么
  • 提供聚合和告警友好的数值化表达
  • 让系统状态可持续采样

Prometheus 的职责

  • 抓取 Metrics
  • 存储 time series
  • 提供 PromQL 查询
  • 执行 recording rules 和 alerting rules
  • 将告警发送到 Alertmanager 等后续通知链路

Grafana 的职责

  • 连接 data source
  • 组织 dashboard 和 panel
  • 提供 variables / Explore / visualization
  • 提供统一查询与展示入口
  • 在需要时提供统一告警管理入口

所以如果把一句话说透,就是:

  • Metrics 决定“看什么”
  • Prometheus 决定“怎么采存算”
  • Grafana 决定“怎么给人看”

11. 如果少了其中一个,会发生什么

没有 Metrics

那就没有统一的可观测数值模型。

结果通常是:

  • 只能看日志
  • 很难做趋势监控
  • 很难做聚合告警

没有 Prometheus

仍然可以有 Metrics,但需要别的系统来承担:

  • 采集
  • 存储
  • 查询

比如别的 TSDB 或云监控平台。

没有 Grafana

Prometheus 仍然可以工作。

此时仍然能:

  • 在表达式浏览器里查
  • 做 recording rules
  • 做 alerting rules

但体验通常会差很多,尤其在:

  • 大盘展示
  • 多图联动
  • 参数切换
  • 多数据源统一查看

这些方面。

所以三者并不是:

  • 缺一个绝对不能运行

而是:

  • 缺一个就会丢掉对应层面的能力

12. 三者为什么常常要一起学

因为真正工程落地时,问题不会只出在某一层。

举几个常见例子:

图为空

排查时通常需要同时判断:

  • Metrics 有没有打出来
  • Prometheus 有没有抓到
  • Grafana query 有没有写对

告警不准

分析时通常需要同时判断:

  • Metrics 语义是不是就不对
  • Prometheus rule 是否合适
  • Grafana 图是不是掩盖了真实问题

查询很慢

分析时通常需要同时判断:

  • Metrics 标签基数是不是爆了
  • Prometheus 查询是不是太重
  • Grafana dashboard 是否一次刷太多 panel

这说明在真实工作里:

  • 这三层必须串起来理解

13. 用一个具体例子彻底打通

以订单服务的下单接口为例。

Metrics 层做什么

先定义并上报:

  • 请求总数
  • 错误总数
  • 下单耗时

例如:

  • http_server_requests_seconds
  • order_created_total
  • order_create_failed_total

Prometheus 层做什么

Prometheus 周期抓取这些指标,并支持写出:

sum(rate(order_created_total[5m]))

或:

histogram_quantile(
  0.95,
  sum by (le) (rate(http_server_requests_seconds_bucket{uri="/orders"}[5m]))
)

同时它还能根据规则判断:

  • 错误率是否过高
  • p95 是否超过阈值

Grafana 层做什么

Grafana 把这些表达式做成:

  • 订单服务总览 dashboard
  • 环境变量切换
  • 接口分维度图表
  • 值班大盘

这样值班人员就不需要每次都手写 PromQL。

这个例子里:

  • Metrics 提供原料
  • Prometheus 提供计算和存储
  • Grafana 提供认知界面

14. 一个常见学习顺序

更自然的学习顺序通常是:

先学 Metrics

先搞清楚:

  • Counter / Gauge / Histogram / Timer
  • 标签基数
  • 命名和单位

因为如果这层错了,后面都建立在错误数据上。

再学 Prometheus

再学:

  • data model
  • scrape
  • TSDB
  • PromQL
  • rules

因为这是把 Metrics 系统化落地的核心。

再学 Grafana

最后学:

  • dashboard
  • panel
  • variables
  • Explore
  • alerting
  • provisioning

因为这一步是把系统变成团队可消费的界面。

这个顺序的好处是:

  • 不容易把展示层误当成本体

15. 如果再加一层 Micrometer,该怎么放

在 Java / Spring Boot 体系里,这一层经常与 Micrometer 一起出现,因此有必要把它也放进同一张图里理解。

在 Java 体系里,常见链路是:

1
2
3
4
5
业务代码
    -> Micrometer
    -> Metrics 暴露
    -> Prometheus 抓取
    -> Grafana 展示

这里:

  • Micrometer 是埋点门面
  • Metrics 是数据抽象
  • Prometheus 是后端系统
  • Grafana 是界面层

所以 MicrometerPrometheus 也不是一回事。

如果把这套东西用到 Caffeine 缓存上

如果场景换成 Caffeine 缓存,这条链路会变得非常具体:

1
2
3
4
5
6
业务代码使用 Caffeine / Spring Cache
    -> Caffeine 统计 hit / miss / load / eviction / size
    -> Micrometer 把这些统计绑定到 MeterRegistry
    -> Spring Boot Actuator 暴露 /actuator/prometheus
    -> Prometheus 周期抓取
    -> Grafana 画出缓存命中率、淘汰、容量和加载耗时

这时候三者的分工就非常清楚:

  • Metrics:缓存命中、miss、淘汰、加载耗时、当前大小这些观测数据
  • Prometheus:负责把这些缓存指标采集下来并支持查询、聚合和告警
  • Grafana:负责把缓存健康度做成 dashboard 给人看

也就是说:

  • 这不是“把 Caffeine 接入 Grafana”
  • 而是“把 Caffeine 的运行统计先变成 Metrics,再交给 Prometheus 和 Grafana”

监控 Caffeine 时,最该关心哪些指标

如果只抓最有价值的一组,通常是:

  • hit / miss
  • hit rate
  • load success / load failure
  • load duration
  • eviction count
  • cache size

为什么是这几个?

  • hit rate 直接反映缓存到底有没有帮助系统减少回源
  • load duration 反映 miss 之后回源到底贵不贵
  • eviction count 反映容量或策略是否太激进
  • cache size 反映当前缓存规模是否接近上限

如果结合 Caffeine 的缓存配置机制,可以概括成:

  • recordStats() 让 Caffeine 开始积累命中、miss、加载、淘汰这类统计
  • maximumSize / maximumWeight、过期策略、刷新策略会直接影响这些指标长什么样
  • removalListener(...) 更适合看具体移除事件,Metrics 更适合看整体趋势

.recordStats() 到底做了什么

最关键的一点是:

  • .recordStats() 只会让 Caffeine 开始在本地内存里累计统计
  • 它不会自己把指标暴露给 Prometheus

也就是说,它做的是:

1
2
开启 Caffeine 内部统计
    -> 产生 CacheStats

它没有做的是:

1
把 CacheStats 自动暴露成 /actuator/prometheus

如果把这一步理解成:

  • .recordStats() = 已经接入监控

那就一定会混乱。

更准确的理解应该是:

  • .recordStats() 只是让缓存开始“记账”
  • Micrometer 才负责把这本账翻译成 Metrics
  • Actuator + micrometer-registry-prometheus 才负责把这些 Metrics 暴露出来

把完整链路写成一行就是:

1
2
3
4
5
recordStats()
    -> Caffeine 内部有了 CacheStats
    -> Micrometer 绑定成 meter
    -> Actuator 暴露 /actuator/prometheus
    -> Prometheus 抓取

所以一个最短判断口诀是:

  • .recordStats() = 开始记账
  • Micrometer = 把账本变成 Metrics
  • Actuator = 把 Metrics 暴露出来
  • Prometheus = 来抓这些 Metrics

少任何一步,都不算真正接入完成。

Spring Boot 自动接入怎么做

如果采用的是 Spring Boot 的缓存抽象,也就是:

  • @EnableCaching
  • @Cacheable
  • CaffeineCacheManager

那么最常见、最省事的做法是走自动接入。

引入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>

    <dependency>
        <groupId>com.github.ben-manes.caffeine</groupId>
        <artifactId>caffeine</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-registry-prometheus</artifactId>
    </dependency>
</dependencies>

这四组依赖分别负责:

  • starter-cache:开启 Spring Cache 体系
  • caffeine:真正的本地缓存实现
  • actuator:提供 metrics 端点
  • micrometer-registry-prometheus:把 metrics 导出成 Prometheus 格式

让底层 Caffeine 开启统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Duration;

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager("user", "dict");
        cacheManager.setCaffeine(Caffeine.newBuilder()
            .maximumSize(10_000)
            .expireAfterWrite(Duration.ofMinutes(10))
            .recordStats());
        return cacheManager;
    }
}

这里最关键的一行就是:

  • .recordStats()

没有它,Caffeine 自己都没有把 hit、miss、eviction 这些统计积累起来,后面 Micrometer 也就没有足够的原料可绑。

暴露 Prometheus 端点

1
2
3
4
5
management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus,metrics

这样通常就能看到:

  • /actuator/metrics
  • /actuator/prometheus

确认自动绑定是否真的成立

自动接入能成立,通常要满足这些前提:

  • cache 是通过 Spring CacheManager 管理的
  • 应用里已经有 Actuator
  • 应用里已经有 micrometer-registry-prometheus
  • 底层 Caffeine 开了 recordStats()
  • 这些 cache 在启动时就已经能被 Spring 看到

如果这些条件满足,Spring Boot / Micrometer 通常会自动把 cache metrics 绑定到 MeterRegistry

直接验证,不要靠猜

应用启动后,应该先做两个检查:

  1. 打开 /actuator/metrics,看看有没有类似 cache.getscache.evictionscache.size
  2. 打开 /actuator/prometheus,看看有没有对应的 cache 相关导出项

如果这里都没有,再去看 Prometheus 抓取配置也没用,因为应用本身还没真正暴露出来。

一个最小使用示意

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Cacheable(cacheNames = "user", key = "#id")
    public User findById(Long id) {
        return loadUserFromDb(id);
    }
}

这一套跑起来以后,流程才是:

1
2
3
4
@Cacheable 命中 user cache
    -> 底层 Caffeine 记录 hit / miss
    -> Micrometer 自动绑定这些统计
    -> /actuator/prometheus 暴露出来

非 Spring Cache 场景怎么手动接入

如果不是用 Spring CacheManager 管理缓存,而是直接写:

  • Cache<K, V> cache = Caffeine.newBuilder()...build()

这时就不应假设 Spring Boot 一定会自动绑上。

这时更稳妥的方式是:

  • 手动创建 cache
  • 手动调用 CaffeineCacheMetrics.monitor(...)

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.cache.CaffeineCacheMetrics;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Duration;

@Configuration
public class LocalCacheConfig {

    @Bean
    public Cache<Long, String> userCache(MeterRegistry registry) {
        Cache<Long, String> cache = Caffeine.newBuilder()
            .maximumSize(10_000)
            .expireAfterWrite(Duration.ofMinutes(10))
            .recordStats()
            .build();

        CaffeineCacheMetrics.monitor(registry, cache, "userCache");
        return cache;
    }
}

这里每一步的作用要分得很清楚:

  • recordStats():让 Caffeine 自己开始统计
  • monitor(registry, cache, "userCache"):把这些统计注册到 MeterRegistry
  • /actuator/prometheus:把 registry 里的内容导出来

如果少了中间这一步:

1
CaffeineCacheMetrics.monitor(registry, cache, "userCache");

此时得到的只是:

  • 缓存内部有统计

而不是:

  • Prometheus 能抓到统计

什么时候通常需要手动接入

下面这些场景,优先按“手动绑定”理解更稳妥:

  • 直接 new 了独立 Caffeine cache
  • cache 不是 Spring CacheManager 管的
  • cache 是运行过程中动态创建的
  • 自动接入没有生效,但缓存本身确实在工作

最小排查顺序

如果出现“已经开了 .recordStats(),但还是没有指标”的情况,可以按这个顺序排:

  1. 有没有 spring-boot-starter-actuator
  2. 有没有 micrometer-registry-prometheus
  3. /actuator/prometheus 是否真的暴露了
  4. cache 是否真的开了 recordStats()
  5. 当前是自动接入,还是应该手动 monitor(...)
  6. 最后再看 Prometheus 的 scrape_configs

Prometheus 在这条链路里具体干什么

Prometheus 并不关心底层是不是 Caffeine,它只关心:

  • 应用有没有把缓存相关 Metrics 暴露出来

抓取配置示意:

1
2
3
4
5
scrape_configs:
  - job_name: "spring-boot"
    metrics_path: "/actuator/prometheus"
    static_configs:
      - targets: ["app:8080"]

抓到之后,就可以写一些非常典型的缓存查询。

例如,5 分钟命中率:

sum(rate(cache_gets_total{cache="user",result="hit"}[5m]))
/
sum(rate(cache_gets_total{cache="user"}[5m]))

例如,5 分钟淘汰速率:

sum(rate(cache_evictions_total{cache="user"}[5m]))

例如,当前缓存大小:

max(cache_size{cache="user"})

例如,平均加载耗时:

sum(rate(cache_load_duration_seconds_sum{cache="user"}[5m]))
/
sum(rate(cache_load_duration_seconds_count{cache="user"}[5m]))

实际写查询时还要注意一点:

  • 具体 metric 名和 label 名可能会随着 Micrometer / Spring Boot 版本、导出方式略有差异
  • 最稳妥的做法始终是先打开 /actuator/prometheus 看实际暴露结果,再写 PromQL

这些查询的意义分别是:

  • 命中率低:缓存收益可能不足
  • 淘汰速率高:容量或策略可能不合理
  • 加载耗时高:miss 的代价可能很贵
  • 大小持续顶格:缓存空间可能不够

Grafana 上通常看什么

到了 Grafana 这一层,重点就不再是“有没有数据”,而是“怎么把缓存状态展示得便于排障和决策”。

一个比较实用的 Caffeine dashboard,通常会放:

  • 命中率趋势
  • hit / miss QPS
  • load success / failure
  • 平均加载耗时
  • eviction 趋势
  • cache size

如果再做得工程化一点,还可以把这些图和下面指标一起放着看:

  • 下游数据库 QPS
  • 下游 RPC RT
  • JVM 堆内存
  • GC 停顿

因为真实线上排查时,通常需要一起判断:

  • 命中率下降,是 key 设计问题、TTL 问题、容量问题,还是下游本来就慢

用 Caffeine 这个例子再反过来看三者关系

如果监控对象换成 Caffeine,本质上不是三者关系变了,而是例子变具体了。

这时可以把三层重新翻译成:

  • Metrics:缓存系统的可观测事实,例如命中、miss、淘汰、大小、加载耗时
  • Prometheus:把这些事实按时间序列保存下来,并支持计算 hit rate、eviction rate、平均 load latency
  • Grafana:把这些结果变成缓存健康度大盘、值班图表和告警入口

所以真正的接入动作不是:

  • Caffeine 直接产出图表界面

而是:

  • Caffeine 先通过 Micrometer 暴露缓存指标
  • Prometheus 再负责采集和查询
  • Grafana 最后负责展示和协作

监控 Caffeine 时几个很容易踩的坑

只配了缓存,没配统计

这时可能已经有缓存功能,但还没有足够好的缓存观测数据。

也就是说:

  • 缓存在跑
  • 但仍然无法判断命中率到底好不好

只看命中率,不看加载耗时

命中率不低,不代表缓存策略就一定合理。

因为还可能出现:

  • 命中率还行
  • 但一旦 miss,回源特别慢

这会让尾延迟非常难看。

忘了 Caffeine 是本地缓存

如果存在多个应用实例,那么每个实例都有自己的本地缓存统计。

这意味着:

  • 某一台机器 hit rate 很高
  • 不代表整个集群所有实例都一样

所以看 Prometheus / Grafana 时,通常要注意实例维度和聚合方式。

把“图空了”误判成 Grafana 问题

缓存图为空时,仍然要按这条链路拆开排查:

  • 是不是应用没暴露指标
  • 是不是 Prometheus 没抓到
  • 还是 Grafana 查询条件写错了

16. 一个最值得记住的心智模型

可以把它概括成一句话:

  • Metrics 是语言,Prometheus 是引擎,Grafana 是仪表盘

更展开一点:

  • Metrics 定义了“系统如何被数值化描述”
  • Prometheus 决定了“这些数值如何被采集、存储、计算和告警”
  • Grafana 决定了“这些结果如何被人高效查看和使用”

如果脑子里始终有这个分层,很多概念混乱都会自动消失。


17. 最常见的错误说法与更准确的说法

错误说法一

  • “Grafana 存了监控数据”

更准确的说法:

  • Grafana 查询并展示后端监控数据,真正存储通常在 Prometheus 或其他数据源

错误说法二

  • “Prometheus 就是 Metrics”

更准确的说法:

  • Prometheus 是处理 Metrics 的系统,不等于 Metrics 这个抽象本身

错误说法三

  • “有 Grafana 就有监控”

更准确的说法:

  • Grafana 是观察入口,真正监控是否成立还取决于 Metrics 设计、Prometheus 采集和告警规则

18. 这篇笔记最该带走的结论

  1. MetricsPrometheusGrafana 是三个不同层次的概念。
  2. Metrics 是观测数据抽象,不是某个具体产品。
  3. Prometheus 是围绕 Metrics 构建的采集、存储、查询和告警系统。
  4. Grafana 是连接数据源并进行可视化、探索与协作的平台。
  5. Metrics 决定数据语义,Prometheus 决定系统处理方式,Grafana 决定人怎么消费这些数据。
  6. 把三者混成一个东西,会直接影响排障和系统设计判断。
  7. 真实链路通常是“应用产生 Metrics -> Prometheus 抓取 -> Grafana 展示”。
  8. 学习顺序通常是先 Metrics,再 Prometheus,最后 Grafana
  9. Grafana 不是数据库,Prometheus 也不是 Metrics 这个概念本身。
  10. 真正成熟的可观测性认知,一定要建立在这种分层理解上。

19. 相关延伸主题

顺着这组专题继续展开,比较自然的延伸主题是:

  • PromQL 深度学习笔记
  • Grafana Dashboard 设计实战笔记
  • Alertmanager 深度学习笔记
  • Micrometer 深度学习笔记

这样整套从埋点到展示的链路就会更完整。