Spring Boot Actuator
1、概览
本文将带你了解 Spring Boot Actuator,以及如何在 Spring Boot 和 WebFlux 中使用、配置和扩展这个监控工具,充分利用响应式编程模型。
2、Actuator 是啥?
从本质上讲,Actuator 为应用带来了生产就绪的功能。
有了 Actuator 后,监控应用程序、收集指标、了解流量或数据库状态就变得易如反掌。
这个库的主要好处是,可以获得生产级工具,而无需自己实际实现这些功能。
Actuator 主要公开应用的运行信息 - 健康状况、指标、信息、转储(dump)、环境等。它使用 HTTP 端点或 JMX Bean 与客户端进行交互。
一旦在 classpath 中添加了该依赖,多个端点就已经开箱即用。与大多数 Spring 模块一样,可以通过多种方式轻松配置或扩展它。
3、入门
首先,在 Spring Boot 项目中添加 spring-boot-actuator 依赖,以启用 Spring Boot Actuator。
Mave:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
该依赖的版本号已经在 spring-boot-starter-parent 中声明了,所以只要你继承了 Parent 项目,不需要手动声明版本号。
Actuator 与技术无关,Actuator 将其模型定义为可插拔和可扩展的,而不依赖 MVC。因此,可以利用 MVC 和 WebFlux 作为底层 Web 实现,还可以通过实现正确的适配器来添加新的实现。也支持 JMX,无需任何额外代码即可暴露端点。
4、端点配置
4.2、默认端点和安全配置
Actuator 禁用了大部分端点。因此,默认情况下只有 /health 和 /info 这两个端点可用。
如果想启用所有端点,可以设置 management.endpoints.web.exposure.include=*。或者,也可以列出应启用的端点。
另外,Actuator 与常规应用 Security 规则共享 Security 配置,从而大大简化了 Security 模型。因此,如果项目中使用了 Spring Security,就必须调整 Actuator 的 Security 规则,以允许 Actuator 端点。
只需添加一个 /actuator/** 条目即可:
@Bean
public SecurityWebFilterChain securityWebFilterChain(
ServerHttpSecurity http) {
return http.authorizeExchange()
.pathMatchers("/actuator/**").permitAll()
.anyExchange().authenticated()
.and().build();
}
所有 Actuator 端点都默认位于 /actuator 路径下。也可以使用配置属性 management.endpoints.web.base-path 来调整路径。
你可以在 Actuator 中文文档 中找到更多细节,
4.3、预定义的端点
Actuator 部分预定义的端点如下:
/auditevents列出了与安全审计相关的事件,如用户登录/注销。此外,还可以根据 Principal 或类型等字段进行过滤。/beans返回BeanFactory中所有可用的 Bean。与/auditevents不同,它不支持过滤。/conditions(之前称为/autoconfig)会生成有关自动配置条件的报告。/configprops允许获取所有@ConfigurationPropertiesBean。/env返回当前环境属性(Environment Properties),也可以检索单个属性。/flyway提供了有关 Flyway 数据库迁移的详细信息。/health汇总了应用的健康状况。/heapdump会构建并返回应用所用 JVM 的 Heap Dump。/info返回一般信息。它可能是自定义数据、构建信息或最新提交的详细信息。/liquibase的行为类似于/flyway,但针对的是 Liquibase。/logfile返回普通应用日志。/loggers能够查询和修改应用的日志级别。/metrics详细介绍了应用的指标。这可能包括通用指标和自定义指标。/prometheus返回的指标与前一个类似,但格式化后可与 Prometheus 服务器一起使用。/scheduledtasks提供了应用中每个计划(定时)任务的详细信息。/sessions列出了 HTTP Session,前提是正在使用 Spring Session。/shutdown可以优雅地关闭应用。/threaddump会 dump 底层 JVM 的线程信息。
4.4、Actuator 端点的 Hypermedia
Spring Boot 添加了一个发现端点,可返回所有可用 Actuator 端点的链接。这有助于发现 Actuator 端点及其相应的 URL。
默认情况下,可通过 /actuator 端点访问该发现端点,向这个 URL 发送 GET 请求,它就会返回各个端点的 Actuator 链接:
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"features-arg0": {
"href": "http://localhost:8080/actuator/features/{arg0}",
"templated": true
},
"features": {
"href": "http://localhost:8080/actuator/features",
"templated": false
},
"beans": {
"href": "http://localhost:8080/actuator/beans",
"templated": false
},
"caches-cache": {
"href": "http://localhost:8080/actuator/caches/{cache}",
"templated": true
},
// 省略其他的 ...
}
如上所示,/actuator 端点会在 _links 字段下返回所有可用的 Actuator 端点。
如果配置了自定义 Management Base Path,则应使用该基本路径作为发现 URL。例如,如果将 management.endpoints.web.base-path 设置为 /mgmt,那么就应该请求 /mgmt 端点来查看链接列表。
注意,当 Management Base Path 设置为 / 时,发现端点会被禁用,以防止与其他映射发生冲突。
4.5、健康指标
可以通过实现 HealthIndicator 接口来轻加自定义指标。ReactiveHealthIndicator 用于实现响应式健康检查。
自定义响应式健康检查:
@Component
public class DownstreamServiceHealthIndicator implements ReactiveHealthIndicator {
@Override
public Mono<Health> health() {
return checkDownstreamServiceHealth().onErrorResume(
ex -> Mono.just(new Health.Builder().down(ex).build())
);
}
private Mono<Health> checkDownstreamServiceHealth() {
// 可以使用 WebClient 来被动地检查健康状况
return Mono.just(new Health.Builder().up().build());
}
}
健康指标的一个方便之处在于,可以将其作为层次结构的一部分进行汇总。
因此,按照前面的例子,可以将所有下游服务归入 downstream-services 类别。只要每个嵌套的服务都是可访问的,那么这个类别就是健康的。
4.6、监控指标分组
可以将健康指标组织成 组(Group),并对所有组员应用相同的配置。
例如,可以在 application.properties 中添加以下内容,创建一个名为 custom 的健康组:
management.endpoint.health.group.custom.include=diskSpace,ping
这样,custom 组就包含了 diskSpace 和 ping 健康指标。
现在,如果调用 /actuator/health 端点,它就会在 JSON 响应中返回新的健康组:
{"status":"UP","groups":["custom"]}
通过健康组,可以看到一些健康指标的综合结果。
在这种情况下,向 /actuator/health/custom 发送请求,响应如下:
{"status":"UP"}
可以通过 application.properties 配置组以显示更多细节:
management.endpoint.health.group.custom.show-components=always
management.endpoint.health.group.custom.show-details=always
现在,如果向 /actuator/health/custom 发起相同的请求,就能看到更多细节:
{
"status": "UP",
"components": {
"diskSpace": {
"status": "UP",
"details": {
"total": 499963170816,
"free": 91300069376,
"threshold": 10485760
}
},
"ping": {
"status": "UP"
}
}
}
也可以只向授权用户显示这些详细信息:
management.endpoint.health.group.custom.show-components=when_authorized
management.endpoint.health.group.custom.show-details=when_authorized
还可以自定义状态映射。
例如,它可以返回 207 状态码,而不是 HTTP 200 OK 响应:
management.endpoint.health.group.custom.status.http-mapping.up=207
上述配置告诉 Spring Boot,如果 custom 组状态为 UP,则返回 207 HTTP 状态码。
4.7、指标
从 Spring Boot 2 开始,内部度量标准已被 Micrometer 支持所取代,我们需要直接与 Micrometer 进行交互。Spring Boot 会自动配置一个类型为 MeterRegistry 的 Bean。
由于 Micrometer 现在是 Actuator 依赖的一部分,所以只要 Actuator 依赖在 classpath 中,就可以使用了。
从 /metrics 端点获取响应:
{
"names": [
"jvm.gc.pause",
"jvm.buffer.memory.used",
"jvm.memory.used",
"jvm.buffer.count",
// ...
]
}
获取特定指标的实际值,例如 /actuator/metrics/jvm.gc.pause:
{
"name": "jvm.gc.pause",
"measurements": [
{
"statistic": "Count",
"value": 3.0
},
{
"statistic": "TotalTime",
"value": 7.9E7
},
{
"statistic": "Max",
"value": 7.9E7
}
],
"availableTags": [
{
"tag": "cause",
"values": [
"Metadata GC Threshold",
"Allocation Failure"
]
},
{
"tag": "action",
"values": [
"end of minor GC",
"end of major GC"
]
}
]
}
4.8、自定义 /info 端点
可以使用 git-commit-id-plugin 依赖添加 git 详细信息。
<dependency>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
</dependency>
同样,也可以使用 Maven 或 Gradle 插件,在其中加入构建信息,包括名称、Group 和版本:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
4.9、创建自定义端点
创建一个 Actuator 端点,用于在应用中查询、启用和禁用 Feature:
@Component
@Endpoint(id = "features")
public class FeaturesEndpoint {
private Map<String, Feature> features = new ConcurrentHashMap<>();
@ReadOperation
public Map<String, Feature> features() {
return features;
}
@ReadOperation
public Feature feature(@Selector String name) {
return features.get(name);
}
@WriteOperation
public void configureFeature(@Selector String name, Feature feature) {
features.put(name, feature);
}
@DeleteOperation
public void deleteFeature(@Selector String name) {
features.remove(name);
}
public static class Feature {
private Boolean enabled;
// get / set 方法
}
}
要获得端点,需要一个 Bean。在本例中,使用 @Component 来实现这一点。此外,还需要用 @Endpoint 来装饰这个 Bean。
端点的路径由 @Endpoint 的 id 参数决定。在本例中,它会将请求路由到 /actuator/features。
准备就绪后,就可以开始定义操作了:
@ReadOperation:映射到 HTTPGET@WriteOperation:映射到 HTTPPOST@DeleteOperation:映射到 HTTPDELETE
Spring Boot 会在运行时注册该端点。
可以在日志中查看到:
[...].WebFluxEndpointHandlerMapping: Mapped "{[/actuator/features/{name}],
methods=[GET],
produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
[...].WebFluxEndpointHandlerMapping : Mapped "{[/actuator/features],
methods=[GET],
produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
[...].WebFluxEndpointHandlerMapping : Mapped "{[/actuator/features/{name}],
methods=[POST],
consumes=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
[...].WebFluxEndpointHandlerMapping : Mapped "{[/actuator/features/{name}],
methods=[DELETE]}"[...]
在上述的日志中,可以看到 WebFlux 是如何暴露新端点的。如果切换到 MVC,也无需更改任何代码。
此外,这还有一些注意事项:
- 与 MVC 没有依赖
- 使用
@Endpoint(id = "features", enableByDefault = false)启用或禁用端点。 - 使用
@DeleteOperation来定义 DELETE 操作。
4.10、扩展现有端点
假如我们想确保应用的生产实例永远不会是 SNAPSHOT 版本。
为此,我们决定改变返回该信息的 Actuator 端点(即 /info)的 HTTP 状态码。如果应用程序碰巧是 SNAPSHOT,就返回不同的 HTTP 状态码。
可以使用 @EndpointExtension 注解或其更具体的 @EndpointWebExtension 或 @EndpointJmxExtension 轻松扩展预定义端点的行为:
@Component
@EndpointWebExtension(endpoint = InfoEndpoint.class)
public class InfoWebEndpointExtension {
private InfoEndpoint delegate;
// 构造函数
@ReadOperation
public WebEndpointResponse<Map> info() {
Map<String, Object> info = this.delegate.info();
Integer status = getStatus(info);
return new WebEndpointResponse<>(info, status);
}
private Integer getStatus(Map<String, Object> info) {
// 如果是 snapshot 则返回 500
return 200;
}
}
4.11、启用所有端点
为了通过 HTTP 访问 actuator 端点,需要同时启用和暴露它们。
默认情况下,除 /shutdown 之外的所有端点都已启用。但是,只有 /health 和 /info 端点是公开的。
可以添加以下配置来暴露所有端点:
management.endpoints.web.exposure.include=*
也可以明确启用特定端点(如 /shutdown):
management.endpoint.shutdown.enabled=true
公开除一个端点(如 /loggers)之外的所有启用端点,
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=loggers
5、总结
本文介绍了 Spring Boot Actuator 含义及其作用。以及如何使用、调整和扩展它。
Ref:https://www.baeldung.com/spring-boot-actuators