使用Micrometer与prometheus集成监控jvm
1.简介
Micrometer 是一个用于收集和报告指标的 Java 库,广泛用于 Spring Boot 和其他 Java 应用。它提供了对系统各项资源的监控支持,包括但不限于 JVM、内存、垃圾回收、线程池、HTTP 请求 等。
Micrometer 支持与多种监控系统的集成,例如 Prometheus、InfluxDB、Datadog 等。
2.前提条件
Java:Micrometer 支持 JDK 8 及以上版本。
Spring Boot:如果是 Spring Boot 项目,可以非常容易地集成 Micrometer;如果不是 Spring Boot 项目,可以手动集成 Micrometer。
监控系统:为了展示指标数据,Micrometer 需要与 Prometheus、InfluxDB、Datadog等监控后端集成。
3.Spring Boot Actuactor集成Prometheus(研发用)
3.1 Spring Boot Actuator 和 Micrometer 的关系和区别
1.概述
- Spring Boot Actuator 是 Spring Boot 提供的一个扩展模块,旨在帮助开发者管理和监控应用程序。它提供了一组内置的端点(如 /actuator/health、/actuator/metrics 等),允许你查看应用的运行状态、监控信息、日志、环境配置等。
- Micrometer 是一个独立的 Java 库,用于度量和报告应用程序的性能指标。它为 Java 应用提供了统一的指标抽象,支持与多种监控系统(如 Prometheus、Datadog、InfluxDB 等)的集成。
2.关系
Spring Boot Actuator 和 Micrometer 是紧密集成的,Spring Boot Actuator 依赖 Micrometer 来收集、导出和暴露应用程序的 metrics(度量指标)。换句话说,Spring Boot Actuator 使用 Micrometer 作为其度量和监控指标的提供者。
具体来说:
- Spring Boot Actuator 包含了 metrics 功能,提供了 /actuator/metrics 端点,用于展示应用程序的各种度量信息。
- 这些度量信息(如 JVM 内存、线程数、HTTP 请求、数据库查询时间等)是通过 Micrometer 来采集的。Actuator 为 Micrometer 提供了一个统一的接口,使得用户能够方便地访问和管理指标。
3.主要区别

4.如何一起使用
在 Spring Boot 应用中,Micrometer 通常是由 Spring Boot Actuator 来自动集成和使用的。
- Actuator 会自动启用 Micrometer 的度量功能,收集默认的 JVM、内存、垃圾回收等指标。
- 可以通过 Spring Boot 配置文件启用或禁用不同类型的指标。例如,可以启用 Prometheus 格式的指标暴露(/actuator/prometheus 端点),并通过 Prometheus 或其他监控系统进行抓取和展示。
5.功能简单概述
| 监控类别 | 具体监控项 |
| JVM 相关 | - JVM 堆内存、非堆内存、垃圾回收(GC)时间与次数 - 类加载和卸载次数 - 线程数、活动线程数 - 方法调用计数、线程池使用情况 - 系统负载、垃圾回收的延迟 |
| 应用性能监控 | - 方法执行时间(计时器和计数器) - 请求响应时间 - 请求成功率 - 应用服务健康状态(如健康检查) |
| 数据库监控 | - 数据库连接池大小、活动连接数、最大连接数 - 数据库查询次数、查询响应时间 - 数据库连接池等待时间 |
| 缓存监控 | - 缓存命中率、缓存未命中率 - 缓存的读取、写入次数 - 缓存的大小与过期情况 |
| HTTP 请求监控 | - 请求计数、成功率、失败率 - 请求延迟、响应时间 - 请求和响应的 HTTP 状态码(如 2xx、4xx、5xx) |
| 消息队列监控 | - 消息队列(如 Kafka、RabbitMQ)的消息发送和接收数量 - 消息处理的延迟 - 消息队列的队列长度 |
| 线程池监控 | - 活跃线程数、最大线程数 - 线程池的任务队列大小 - 线程池的任务完成数、执行时间 |
| 网络监控 | - 网络请求数、网络错误数 - 网络流量(上行、下行) - 网络连接的活跃状态 |
| 磁盘监控 | - 磁盘空间使用率、可用空间 - 文件系统的 I/O 操作统计 |
| 自定义指标(为未知) | - 用户自定义的指标(如业务逻辑的处理时间、失败次数等) |
3.2 添加MicroMeter Prometheus监控指标
3.2.1 添加Maven依赖
在 pom.xml 中加入 Spring Boot Actuator 和 Micrometer 相关依赖:
<dependency> <groupId>com.imilab.argus</groupId> <artifactId>iot-base-actuator</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
3.2.2 添加公共配置
spring:
cloud:
nacos:
config:
shared-configs:
- data-id: common-argus
group: common
refresh: true
3.2.3 独立配置(可选)
在 application.properties 或 application.yml 中配置,启用你想要监控的 JVM 指标。
application.yml 示例:
management:
endpoints:
web:
exposure:
include:
# 暴露健康检查端点
- health
# 暴露普罗米修斯指标端点
- prometheus
# 暴露指标列表端点
- metrics
metrics:
tags:
namespace: ${runtime.env}
application: ${spring.application.name}
3.3 安全
actuator端点默认绑定server.port端口,与业务接口使用相同端口,因此在开放业务端口的同时也会暴露actuator端点,会造成信息泄露等严重的安全隐患。
3.3.1 外网访问服务
针对这类直接对公网开放端口的服务,应为actuator组件配置单独端口,防止开放业务端口时暴露actuator端点。
# 配置独立端口,只开放8080
server.port=8080
management.port=8090
3.3.2 业务服务
集群内部服务可使用默认端口,但禁止在对外服务中直接配置路由将actuator端点对外开放。
禁止开放所有actuator端点,端点按需配置。
# 反例
# 禁止
management:
endpoints:
web:
exposure:
include:
- "*"
3.4 自定义指标
添加Spring Boot自动扫描路径
@SpringBootApplication(scanBasePackages = {"com.imilab.base.actuator"})
3.4.1 @Timed
默认会统计接口执行时间,无需再为接口添加@Timed注解
使用场景:监控某些micrometer未支持的组件,或关心的核心业务方法,例如监控iotdb的写入时间,
@Timed 注解主要用于记录方法的执行时间。它会生成一个Timer度量,包含如下信息:
- 执行时间:方法的总执行时间、最大执行时间。
- 调用次数:方法被调用的总次数。
@Timed(value = "argus.things.queryProperty")
@Override
public ThingValueQuery queryPropertyLatest(String iotId, Integer thingId) {
1. ...}
- argus_things_queryProperty_seconds_max: 最大执行时间
- argus_things_queryProperty_seconds:总次数
- argus_things_queryProperty_seconds_sum: 总执行时间
# HELP argus_things_queryProperty_seconds_max
# TYPE argus_things_queryProperty_seconds_max gauge
argus_things_queryProperty_seconds_max{application="iot-device-things",class="com.imilab.argus.iot.device.things.application.service.impl.ThingValueServiceImpl",exception="none",method="queryPropertyLatest",namespace="local",} 0.3813045
# HELP argus_things_queryProperty_seconds
# TYPE argus_things_queryProperty_seconds summary
argus_things_queryProperty_seconds_count{application="iot-device-things",class="com.imilab.argus.iot.device.things.application.service.impl.ThingValueServiceImpl",exception="none",method="queryPropertyLatest",namespace="local",} 13.0
argus_things_queryProperty_seconds_sum{application="iot-device-things",class="com.imilab.argus.iot.device.things.application.service.impl.ThingValueServiceImpl",exception="none",method="queryPropertyLatest",namespace="local",} 0.5584831
3.4.2 @Counted
@Counted注解用于记录方法的调用次数
@Counted(value = "argus.sms.send")
public void sendSMS(){
}
- argus_sms_send_total: 执行总次数
# HELP argus_sms_send_total
# TYPE argus_sms_send_total counter
argus_sms_send_total{application="iot-device-things",class="com.imilab.argus.iot.device.things.application.service.impl.ThingValueServiceImpl",exception="none",method="queryPropertyLatest",namespace="local",result="success",} 3.0
3.5 问题
3.5.1 FastJson序列化导致的Prometheus指标格式错误
- 问题产生条件:
Spring配置了全局FastJsonHttpMessageConverter
@Configuration @EnableWebMvc public class JsonConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { //fastjson的全局序列化方式 configureFastJsonHttpMessageConverter(converters); } private void configureFastJsonHttpMessageConverter(List<HttpMessageConverter<?>> converters) { // 定义一个convert转换消息的对象; FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); //配置Content-Type List<MediaType> supportedMediaTypes = new ArrayList<>(); supportedMediaTypes.add(MediaType.ALL); fastConverter.setSupportedMediaTypes(supportedMediaTypes); // 添加fastjson的配置信息 FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures( //SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteNonStringKeyAsString ); // convert添加配置信息. fastConverter.setFastJsonConfig(fastJsonConfig); // 将convert添加到converters当中. converters.add(fastConverter); }
设置了支持所有MediaType
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); List<MediaType> supportedMediaTypes = new ArrayList<>(); supportedMediaTypes.add(MediaType.ALL);
- 解决方式
方式1:添加StringHttpMessageConverter。
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // string序列化 configureStringHttpMessageConverter(converters); //fastjson的全局序列化方式 configureFastJsonHttpMessageConverter(converters); } private void configureStringHttpMessageConverter(List<HttpMessageConverter<?>> converters){ StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(); List<MediaType> supportedMediaTypes = new ArrayList<>(); supportedMediaTypes.add(MediaType.TEXT_PLAIN); supportedMediaTypes.add(MediaType.ALL); stringHttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes); converters.add(stringHttpMessageConverter); }
方式2:删除FastJson全局序列化配置,使用Spring Boot Starer Web默认序列化方式。
4.集成 Prometheus
4.1 自建
在 Prometheus 配置中,添加对你的应用的监控地址。
scrape_configs: - job_name: 'my-app' static_configs: - targets: ['<your-app-host>:<port>']
4.2 阿里云prometheus
由于主要使用阿里云服务,在创建阿里云 ACK 集群时已默认启用 Prometheus 服务,因此接下来大部分演示将基于阿里云的产品和服务进行。
1.搜索arms→接入管理→选择集群(使用debug演示,撰写本文档时,prod还未接入监控)

2. 指标采集→servicemonitor→新增

3. 应用实时监控服务→prometheus监控→prometheus告警规则

番外(状态查看验证)
在某些情况下,如果监控的服务没有数据,可以通过以下小技巧先排除运维侧的问题:检查服务是否成功接入。
接入管理→自监控

4.新建一条告警规则
以下就需要运维人员熟悉监控key以及prometheus sql配置了

以下是查看 Key 的方式:
无论是自建的 Prometheus 还是阿里云 Prometheus,都提供了各自的控制台。在控制台中,您可以输入 Key 前缀(例如:jvm),系统会自动关联并显示相关的 Key。
接下来,我们将使用阿里云 Prometheus 控制台进行演示。
a) 应用实时监控服务→prometheus监控→实例列表
b) 指标管理
阿里云故障,这里先空缺
5.grafana
在 Grafana 中创建 Prometheus 数据源,然后通过 Grafana 仪表盘可视化这些指标。
这里我们使用阿里云的 Grafana,它的使用方式与自建的 Grafana 并没有太大区别,主要的差异在于阿里云的 Grafana 会自动配置好数据源。
(部署创建grafana步骤省略)
1.登录阿里云grafana
点击左侧栏→仪表板

2.新建→导入

3.可以登录 Grafana 官网查找所需的模板,找到适合自己需求的模板可能需要一些时间。
https://grafana.com/grafana/dashboards/4701-jvm-micrometer/
找到模版后复制模版id

4.回到第二步,把模版id输入进去,就可以使用该模版了

选择数据源,这里阿里云自动关联阿里云上面的prometheus,现在直接选择即可

5.导入后查看看板

6.性能优化
6.1 减少指标收集对应用性能的影响:
- 使用较长的采集间隔。
- 只收集最重要的指标,避免过多的指标采集。
6.2 控制指标暴露频率:
- 配置 management.metrics.export.prometheus.enabled 来控制是否启用 Prometheus 指标的暴露。
7.常见问题与排查
7.1 无法看到指标
- 确保已正确配置 application.yml 或 application.properties 文件,启用相应的指标。
- 查看日志,检查是否有相关的错误信息。
7.2 指标格式问题:
- 确保 Prometheus 正确抓取暴露的指标端点,检查 prometheus.yml 配置是否正确。
8.总结
- Micrometer 提供了一个强大的方式来监控 JVM 和应用的性能指标,支持多种监控后端,如 Prometheus、InfluxDB 等。
- 配置简单,能够自动收集 JVM、内存、线程等常见指标,(只是这里仅演示了jvm,http等都可以监控空)并可以通过 MeterRegistry 提供自定义指标。
- 集成 Prometheus 和 Grafana,可以对指标进行可视化和告警。

浙公网安备 33010602011771号