Spring Boot Actuator:如何通过JMX或HTTP暴露JVM与应用指标的细节

Spring Boot Actuator:JMX与HTTP暴露JVM与应用指标细节

各位同学,大家好。今天我们来深入探讨Spring Boot Actuator,重点讲解如何通过JMX和HTTP这两种方式,将JVM和应用级别的指标信息暴露出来,以便进行监控、分析和诊断。

Actuator 简介

Spring Boot Actuator是一个生产就绪的模块,它提供了一系列端点(Endpoints),用于监控和管理你的Spring Boot应用。这些端点可以暴露应用的内部状态,例如健康状况、指标、配置信息、线程转储等等。Actuator 默认提供了一些内置的端点,同时也允许我们自定义端点来暴露特定的信息。

暴露指标的必要性

在生产环境中,了解应用程序的运行状况至关重要。指标(Metrics)是量化的度量,可以帮助我们理解应用程序的行为,例如:

  • JVM 指标: 堆内存使用情况、垃圾回收频率、线程数等,可以帮助我们诊断内存泄漏、性能瓶颈等问题。
  • 应用指标: 请求处理时间、数据库连接池使用情况、缓存命中率等,可以帮助我们优化应用程序性能、排查业务逻辑问题。

通过将这些指标暴露出来,我们可以使用各种监控工具(例如Prometheus、Grafana、JConsole)来收集、分析和可视化这些数据,从而及时发现并解决问题。

通过HTTP暴露指标

1. 添加依赖

首先,需要在 pom.xml 文件中添加 Actuator 的依赖:

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

2. 配置端点暴露

默认情况下,Actuator 只暴露了 healthinfo 两个端点。我们需要在 application.propertiesapplication.yml 文件中配置 management.endpoints.web.exposure.include 属性,来指定需要暴露的端点。

  • 暴露所有端点:

    management.endpoints.web.exposure.include=*
  • 暴露指定的端点:

    management.endpoints.web.exposure.include=health,info,metrics,threaddump,heapdump
  • 暴露 metrics 端点,但排除特定的指标:

    management.endpoints.web.exposure.include=metrics
    management.metrics.distribution.percentiles-histogram.http.server.requests=true
    management.metrics.distribution.percentiles.http.server.requests=0.5, 0.95, 0.99
    management.metrics.enable.process.cpu.usage=false  #禁用 process.cpu.usage 指标

3. 访问端点

配置完成后,重启应用,就可以通过 HTTP 访问 Actuator 的端点了。默认情况下,Actuator 的端点都位于 /actuator 路径下。例如,要访问 metrics 端点,可以访问 http://localhost:8080/actuator/metrics

4. Metrics 端点详解

metrics 端点提供了丰富的指标信息。访问 http://localhost:8080/actuator/metrics 会返回一个 JSON 对象,包含所有可用的指标名称。

{
  "names": [
    "jvm.memory.used",
    "jvm.memory.max",
    "jvm.gc.memory.allocated",
    "jvm.gc.max.data.size",
    "jvm.threads.live",
    "process.uptime",
    "system.cpu.usage",
    "http.server.requests"
  ]
}

要获取特定指标的详细信息,可以在 metrics 端点后面加上指标名称。例如,要获取 jvm.memory.used 指标的信息,可以访问 http://localhost:8080/actuator/metrics/jvm.memory.used

{
  "name": "jvm.memory.used",
  "description": "The amount of used memory",
  "baseUnit": "bytes",
  "measurements": [
    {
      "statistic": "VALUE",
      "value": 2.3434456E7
    }
  ],
  "availableTags": [
    {
      "tag": "area",
      "values": [
        "heap",
        "nonheap"
      ]
    }
  ]
}

这个 JSON 对象包含了指标的名称、描述、单位、测量值和可用的标签。measurements 数组包含了指标的统计信息,例如 VALUE 表示当前值。availableTags 数组包含了可以用来过滤指标的标签。例如,可以使用 area=heap 来获取堆内存的使用情况。

5. 自定义指标

除了 Actuator 提供的内置指标,我们还可以自定义指标来暴露应用程序特定的信息。可以使用 MeterRegistry 接口来创建和管理指标。

首先,需要在 Spring Bean 中注入 MeterRegistry

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyMetrics {

    private final MeterRegistry meterRegistry;

    @Autowired
    public MyMetrics(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    public void incrementCustomCounter() {
        meterRegistry.counter("my.custom.counter").increment();
    }

    public void recordCustomTimer(long duration) {
        meterRegistry.timer("my.custom.timer").record(duration, java.util.concurrent.TimeUnit.MILLISECONDS);
    }

    public void registerCustomGauge(double value) {
      meterRegistry.gauge("my.custom.gauge", value);
    }
}

然后,在需要记录指标的地方调用相应的方法:

@Autowired
private MyMetrics myMetrics;

@GetMapping("/my-endpoint")
public String myEndpoint() {
    long startTime = System.currentTimeMillis();
    // 执行一些业务逻辑
    try {
      Thread.sleep(100); //模拟耗时操作
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
    }
    long endTime = System.currentTimeMillis();
    myMetrics.incrementCustomCounter();
    myMetrics.recordCustomTimer(endTime - startTime);
    myMetrics.registerCustomGauge(Math.random()); // 模拟一个随机值
    return "Hello, world!";
}

在这个例子中,我们创建了一个名为 my.custom.counter 的计数器,一个名为 my.custom.timer 的计时器和一个名为 my.custom.gauge 的指标。每次访问 /my-endpoint 时,计数器会递增,计时器会记录请求的处理时间,指标会记录一个随机值。

6. Micrometer 和 MetricRegistry

Spring Boot Actuator 使用 Micrometer 作为指标收集的抽象层。Micrometer 支持多种指标后端,例如 Prometheus、InfluxDB、Datadog 等。MeterRegistry 接口是 Micrometer 的核心接口,用于创建和管理指标。

Spring Boot 会自动配置一个 MeterRegistry Bean,我们可以直接注入到我们的代码中使用。也可以通过配置 management.metrics.export 属性来指定使用哪个指标后端。例如,要使用 Prometheus,可以添加以下依赖:

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

并配置以下属性:

management.metrics.export.prometheus.enabled=true
management.endpoints.web.exposure.include=prometheus

然后,就可以通过 /actuator/prometheus 端点访问 Prometheus 格式的指标数据了。

通过 JMX 暴露指标

JMX(Java Management Extensions)是一种 Java 技术,用于监控和管理 Java 应用程序。Actuator 也可以通过 JMX 将指标暴露出来,方便我们使用 JConsole 等 JMX 客户端来查看和管理指标。

1. 配置 JMX

默认情况下,Actuator 会自动将指标注册到 JMX MBeanServer 中。我们可以通过配置 spring.jmx.enabled 属性来启用或禁用 JMX。

spring.jmx.enabled=true

2. 使用 JConsole 连接

启动应用程序后,可以使用 JConsole 连接到应用程序的 JMX MBeanServer。JConsole 是 JDK 自带的 JMX 客户端,位于 JDK 的 bin 目录下。

启动 JConsole 后,选择 "Local" 选项卡,找到你的 Spring Boot 应用程序,点击 "Connect"。

3. 查看指标

连接成功后,可以在 JConsole 的 "MBeans" 选项卡中找到 Actuator 暴露的指标。Actuator 的指标都位于 org.springframework.boot.actuate.metrics 域名下。

例如,要查看 jvm.memory.used 指标,可以找到 org.springframework.boot.actuate.metrics.jvm.memory.used MBean,然后查看它的 "Attributes" 属性。

4. 自定义 JMX 指标

和 HTTP 方式一样,我们可以自定义 JMX 指标。但是,自定义 JMX 指标的方式与自定义 HTTP 指标略有不同。我们需要使用 @ManagedResource@ManagedAttribute 注解来标注需要暴露的类和方法。

import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;

@Component
@ManagedResource(objectName = "com.example:type=MyMetrics,name=CustomMetrics")
public class MyJmxMetrics {

    private double myCustomValue = 0.0;

    @ManagedAttribute(description = "My Custom Value")
    public double getMyCustomValue() {
        return myCustomValue;
    }

    public void setMyCustomValue(double myCustomValue) {
        this.myCustomValue = myCustomValue;
    }

    public void updateValue() {
        this.myCustomValue = Math.random();
    }
}

在这个例子中,我们创建了一个名为 MyJmxMetrics 的类,并使用 @ManagedResource 注解将其标注为一个 JMX MBean。objectName 属性指定了 MBean 的名称。getMyCustomValue 方法使用 @ManagedAttribute 注解将其标注为一个 JMX 属性。

要更新 JMX 指标的值,可以调用 setMyCustomValue 方法或 updateValue 方法。

@Autowired
private MyJmxMetrics myJmxMetrics;

@GetMapping("/update-jmx-metric")
public String updateJmxMetric() {
    myJmxMetrics.updateValue();
    return "JMX metric updated!";
}

访问 /update-jmx-metric 端点后,MyJmxMetrics MBean 的 MyCustomValue 属性的值将会被更新。

HTTP 与 JMX 的选择

那么,在选择使用 HTTP 还是 JMX 来暴露指标时,应该考虑哪些因素呢?

特性 HTTP JMX
易用性 简单易用,可以直接通过浏览器访问 配置稍复杂,需要 JMX 客户端
标准化 RESTful API,易于集成到各种监控工具中 JMX 标准,但集成可能需要额外的适配器
安全性 可以通过 Spring Security 进行细粒度的权限控制 安全性依赖 JMX 客户端和 JMX 代理的配置
实时性 实时性较高,可以获取最新的指标数据 实时性取决于 JMX 客户端的轮询频率
网络穿透性 相对容易,可以通过防火墙和代理服务器访问 需要配置 JMX 代理和防火墙规则,穿透性较差
适用场景 云原生环境,需要集成到监控平台中 传统的企业级应用,需要使用 JMX 客户端监控

总的来说,HTTP 方式更适合云原生环境,因为它简单易用,易于集成到各种监控平台中。JMX 方式更适合传统的企业级应用,因为它可以使用 JConsole 等 JMX 客户端进行监控和管理。

安全性考虑

无论是使用 HTTP 还是 JMX 暴露指标,都需要注意安全性。Actuator 的端点可能会暴露敏感信息,例如配置信息、环境变量、数据库连接信息等。因此,我们需要采取一些安全措施来保护 Actuator 的端点。

  • 使用 Spring Security 进行认证和授权: 可以使用 Spring Security 来限制对 Actuator 端点的访问。例如,可以只允许具有特定角色的用户访问 metrics 端点。
  • 禁用不需要的端点: 可以禁用不需要的端点,以减少潜在的安全风险。
  • 使用 HTTPS: 使用 HTTPS 可以加密 Actuator 端点的数据传输,防止数据被窃听。
  • 限制 JMX 客户端的访问: 可以使用 JMX 代理和防火墙规则来限制 JMX 客户端的访问。

实战案例:Prometheus + Grafana 监控

下面,我们来演示如何使用 Prometheus 和 Grafana 来监控 Spring Boot 应用程序的指标。

1. 添加 Prometheus 依赖

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

2. 配置 Prometheus 端点

management.metrics.export.prometheus.enabled=true
management.endpoints.web.exposure.include=prometheus

3. 安装和配置 Prometheus

下载并安装 Prometheus,然后配置 Prometheus 的配置文件 prometheus.yml,添加以下内容:

scrape_configs:
  - job_name: 'spring-boot-app'
    metrics_path: '/actuator/prometheus'
    scrape_interval: 5s
    static_configs:
      - targets: ['localhost:8080'] # 你的 Spring Boot 应用的地址

4. 启动 Prometheus

启动 Prometheus,然后访问 Prometheus 的 Web 界面(通常是 http://localhost:9090),就可以看到 Spring Boot 应用程序的指标数据了。

5. 安装和配置 Grafana

下载并安装 Grafana,然后添加 Prometheus 数据源。

6. 创建 Grafana Dashboard

创建 Grafana Dashboard,并添加各种图表来可视化 Spring Boot 应用程序的指标数据。例如,可以创建一个图表来显示 JVM 堆内存的使用情况,可以使用以下 Prometheus 查询语句:

jvm_memory_used_bytes{area="heap"}

通过 Prometheus 和 Grafana,我们可以实时监控 Spring Boot 应用程序的各种指标,及时发现并解决问题。

常用指标及其含义

以下是一些常用的 Spring Boot Actuator 指标及其含义:

指标名称 描述 单位
jvm.memory.used JVM 已使用的内存量 bytes
jvm.memory.max JVM 可使用的最大内存量 bytes
jvm.gc.memory.allocated JVM 垃圾回收器分配的内存量 bytes
jvm.threads.live JVM 活跃线程数
process.uptime 应用程序的运行时间 seconds
system.cpu.usage 系统 CPU 使用率
http.server.requests HTTP 请求处理时间 seconds
http.server.requests.seconds.count HTTP 请求总数
http.server.requests.seconds.sum HTTP 请求总耗时 seconds
database.connections.active 数据库连接池中活跃的连接数
database.connections.max 数据库连接池中最大的连接数

一些提示和技巧

  • 合理配置指标的暴露: 不要暴露所有端点,只暴露需要的端点,以减少潜在的安全风险。
  • 使用标签来过滤指标: 使用标签可以更精确地获取需要的指标数据。
  • 自定义指标时,选择合适的指标类型: 根据实际情况选择合适的指标类型,例如计数器、计时器、仪表盘等。
  • 使用 Micrometer 的统一接口: 使用 Micrometer 的统一接口可以方便地切换不同的指标后端。
  • 定期审查和更新指标配置: 随着应用程序的发展,指标配置可能需要定期审查和更新。

总结

今天我们详细讲解了如何通过HTTP和JMX两种方式暴露Spring Boot Actuator的指标,以及如何使用Prometheus和Grafana进行监控。掌握这些技术,可以帮助我们更好地理解应用程序的行为,及时发现并解决问题,保障应用程序的稳定运行。记住,选择合适的方式、注意安全配置、合理利用指标,才能真正发挥Actuator的作用。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注