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 只暴露了 health 和 info 两个端点。我们需要在 application.properties 或 application.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的作用。