使用Micrometer与prometheus集成监控jvm

1.简介

  Micrometer 是一个用于收集和报告指标的 Java 库,广泛用于 Spring Boot 和其他 Java 应用。它提供了对系统各项资源的监控支持,包括但不限于 JVM内存垃圾回收线程池HTTP 请求 等。

  Micrometer 支持与多种监控系统的集成,例如 PrometheusInfluxDBDatadog 等。

 

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 ActuatorMicrometer 是紧密集成的,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,可以对指标进行可视化和告警。

 

posted @ 2025-03-14 18:11  小家电维修  阅读(399)  评论(0)    收藏  举报