Spring Boot 从 2.0 开始就把底层指标系统换成了 Micrometer,它相当于指标界的 SLF4J,屏蔽了不同监控后端的差异。只要在代码里用统一的 API 记录指标,换监控后端时几乎不用改业务代码。而 Prometheus 作为当下最主流的开源监控系统,配合 Grafana 可以轻松实现指标可视化。把两者打通,是搭建应用监控体系最常见的一条路径。

一、理解 Micrometer 与 Prometheus 的关系
很多刚接触监控的同学容易把 Micrometer 和 Prometheus 混为一谈,这里先厘清概念。Micrometer 是一个指标门面库,运行在应用程序内部,负责定义和收集指标;Prometheus 是一个独立的时序数据库和监控系统,负责从应用拉取数据、存储和查询。两者之间通过 Prometheus 特有的文本暴露格式通信。
具体来说,当你在 Spring Boot 里调用 MeterRegistry.counter("order.created") 时,Micrometer 会在内存里维护这个计数器的状态。当你引入了 micrometer-registry-prometheus 依赖后,Micrometer 会提供一个 PrometheusMeterRegistry,它把所有指标渲染成 Prometheus 可解析的文本格式。Actuator 的 /actuator/prometheus 端点访问时返回的就是这份文本,Prometheus 服务端定时抓取这个端点,数据就进了时序库。
这套机制的好处是解耦:如果哪天公司换成了 InfluxDB 或者 Datadog,你只需要换依赖和注册器实现,业务代码里的埋点一行都不用动。这也是推荐通过 Micrometer 间接对接而不是直接写 Prometheus 客户端 SDK 的主要原因。
二、引入依赖并完成基础配置
第一步是添加 Prometheus 注册器依赖。如果项目已经引入了 spring-boot-starter-actuator,只需要再加一个依赖即可:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>接下来在配置文件中暴露端点。Spring Boot 2.x 用 properties 或 yml 均可,下面以 yml 为例:
management:
endpoints:
web:
exposure:
include: health,prometheus
metrics:
tags:
application: ${spring.application.name}
export:
prometheus:
enabled: true这里有一个很关键的配置:management.metrics.tags.application。它会给所有指标打上一个应用名标签,在多服务共用一个 Prometheus 的场景下,没有这个标签你几乎无法区分数据来自哪个服务,建议务必加上。配置完成后启动应用,访问 http://127.0.0.1:8080/actuator/prometheus,能看到类似下面的文本输出就说明成功了:
# HELP jvm_memory_used_bytes ...
# TYPE jvm_memory_used_bytes gauge
jvm_memory_used_bytes{area="heap",id="PS Eden Space",application="order-service",} 4.3E7三、在业务代码中记录自定义指标
内置指标只能反映 JVM、HTTP 请求等通用信息,监控的核心价值往往在业务指标上。Micrometer 提供了几种常用的计量器类型,选择合适的类型很重要:
- Counter(计数器):只增不减的量,比如订单创建次数、异常发生次数。
- Gauge(瞬时值):某个时刻的值,比如当前队列长度、缓存条目数。
- Timer(耗时):记录事件耗时和次数,适合接口或任务执行时长统计。
- DistributionSummary(分布):记录事件的值分布,比如一次请求传输的字节数。
下面是一个典型的订单服务埋点示例,通过构造器注入 MeterRegistry,在业务方法中同时记录下单次数和处理耗时:
@Service
public class OrderService {
private final Counter orderCounter;
private final Timer orderTimer;
public OrderService(MeterRegistry registry) {
this.orderCounter = Counter.builder("order.created.total")
.description("订单创建总数")
.tag("channel", "app")
.register(registry);
this.orderTimer = Timer.builder("order.process.duration")
.description("订单处理耗时")
.publishPercentileHistogram()
.register(registry);
}
public void createOrder(OrderRequest request) {
orderTimer.record(() -> {
// 实际下单逻辑
doCreate(request);
orderCounter.increment();
});
}
}有几个实践上的注意点。第一,指标命名建议用小写加英文句点的风格,Micrometer 会自动把它转成 Prometheus 的下划线格式,order.created.total 最终会变成 order_created_total。第二,标签的取值要控制在有限集合内,千万不要把用户 ID、订单号这类高基数值放进标签,否则指标维度爆炸会直接拖垮 Prometheus。第三,Timer 加上 publishPercentileHistogram() 后可以配合 Prometheus 的 histogram_quantile 函数计算 P95、P99 分位耗时,对性能分析非常有用。
还有一种常见需求是对既有对象做 Gauge 监控,比如监控某个内存队列的长度。可以借助强引用持有被监控对象,避免 Gauge 指向的对象被垃圾回收后一直返回 NaN:
@Service
public class QueueMonitor {
private final LinkedBlockingQueue<Task> queue = new LinkedBlockingQueue<>(1000);
@PostConstruct
public void init() {
// 使用强引用持有 list,防止被 GC 后 gauge 失效
List<LinkedBlockingQueue<Task>> holder = new ArrayList<>();
holder.add(queue);
Gauge.builder("task.queue.size", holder, Collection::size)
.description("待处理任务队列长度")
.register(registry);
}
}四、配置 Prometheus 抓取与验证
应用侧准备就绪后,需要让 Prometheus 知道去哪里抓数据。修改 Prometheus 的配置文件 prometheus.yml,添加一个抓取任务:
scrape_configs:
- job_name: 'order-service'
metrics_path: '/actuator/prometheus'
scrape_interval: 15s
static_configs:
- targets: ['192.168.0.10:8080']
labels:
env: 'prod'服务实例少的时候静态配置够用,但如果部署在 Kubernetes 上,更推荐使用服务发现,把 pod 的所有者信息自动作为标签,避免每次扩容都手动改配置。配置重载后访问 Prometheus 自带的 Web 界面,在 Status 菜单的 Targets 页面能看到目标处于 UP 状态即表示抓取正常。
随后可以试着查询一下,比如统计每分钟的订单创建速率:rate(order_created_total[1m]),这比直接看计数器的累计值有意义得多。Grafana 接入 Prometheus 数据源后,可以把这类查询语句直接做成面板,配合官方社区发布的 Spring Boot 监控仪表盘模板,JVM 内存、GC、线程、HTTP 请求等常见图表基本可以开箱即用。
五、常见问题排查思路
实际落地时难免踩坑,这里总结几个高频问题。一是端点访问返回 404,多半是 management.endpoints.web.exposure.include 没有包含 prometheus,或者项目里存在自定义的安全拦截器把 Actuator 路径拦掉了,需要放行该路径。二是 Prometheus 页面上目标一直显示 DOWN,先确认网络连通性,再用 curl 直接请求应用的端点看返回内容,同时注意抓取超时时间要小于抓取间隔。
三是指标数据出现断点或丢失。Prometheus 是拉取模型,应用重启会导致计数器归零,这在 Prometheus 端是正常现象,查询时配合 rate() 或 increase() 函数可以正确处理计数器重置。另外要检查指标基数,可以用 count by (__name__)({__name__=~".+"}) 之类的查询定位哪个指标维度异常膨胀,及时清理不合理的标签。
四是 Spring Boot 3.x 用户的依赖坐标有变化,Actuator 相关模块迁移到了新的命名空间,引入依赖时注意groupId要写 org.springframework.boot 对应的新版本,同时确认 Micrometer 版本与 Boot 版本匹配,一般由 Boot 的依赖管理自动对齐,不需要手动指定版本号。
整体来看,Micrometer 加 Prometheus 的组合配置成本不高,却能让应用从黑盒变成白盒。建议先从内置指标接入做起,再逐步补充业务埋点,让监控数据真正参与到日常的容量评估和故障定位中去。
MicrometerSpring BootPrometheus修改时间:2026-09-06 04:10:41