《Spring Boot Actuator详解与深刻应用》预计包括三篇,第一篇重点讲Spring Boot Actuator 1.x的应用与定制端点;第二篇将会对比Spring Boot Actuator 2.x 与1.x的区别,以及应用和定制2.x的端点;第三篇将会介绍Actuator metric指标与Prometheus和Grafana的使用结合。这部份内容很经常使用,且较为入门,欢迎你们的关注。html
本文系《Spring Boot Actuator详解与深刻应用》中的第二篇。在上一篇文章:Spring Boot Actuator详解与深刻应用(一):Actuator 1.x主要讲了Spring Boot Actuator 1.x的应用与定制端点。Spring Boot2.0的正式版已经发布有一段时间了,目前已经到了2.1.0.RELEASE
。关于Spring Boot2.x的特性,在此不详细叙述了,可是其流行的趋势是显而易见的。java
本文将会对比Spring Boot Actuator 2.x 与1.x的区别,以及应用和定制2.x的端点。重点介绍最新的2.x版本的Actuator。react
Actuator 2.x继续保持其基本功能,但简化其模型,扩展其功能并包含合适的默认值。首先,这个版本变得与特定框架解耦;此外,它经过将其与应用程序合并来简化其安全模型;最后,在各类变化中,有些变化是巨大的,这包括HTTP请求/响应以及提供的Java API。此外,最新版本支持CRUD模型,而不是旧的RW(读/写)模型。git
在Actuator 1.x中,它与Spring MVC绑定,所以与Servlet API相关联。而在2.x中,Actuator定义了它的模型可插拔且可扩展,而不依赖于MVC。所以,经过这个新模型,咱们能够像MVC同样使用WebFlux做为底层Web技术。此外,之后的框架能够经过实现特定的适配器来增长到这个模型中。在没有任何额外的代码的状况下,JMX仍然支持暴露端点。github
引入以下的依赖:web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
复制代码
和使用的Spring Boot Actuator 1.x并无太大的区别。redis
不一样于以前的Actuator 1.x,Actuator 2.x 的大多数端点默认被禁掉。 Actuator 2.x 中的默认端点增长了/actuator前缀。spring
默认暴露的两个端点为/actuator/health 和 /actuator/info。咱们能够经过设置以下的属性:数据库
management.endpoints.web.exposure.include=*
复制代码
可使得全部的端点暴露出来。此外,咱们也能够列出须要暴露的端点或者排除某些端点。如:json
management.endpoints.web.exposure.exclude=env,beans
复制代码
下面咱们看一下可用的端点,他们大部分在1.x中已经存在。尽管如此,有些端点新增,有些被删除,有些被重构。
@ConfigurationProperties
的bean对象Actuator端点是敏感的,必须防止未经受权的访问。 若是应用程序中存在Spring Security,则默认状况下使用基于表单的HTTP基自己份验证来保护端点。使用Spring Security保护Actuator的端点访问。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
复制代码
为了应用Actuator的安全规则,咱们增长以下的配置:
@Bean
public SecurityWebFilterChain securityWebFilterChain( ServerHttpSecurity http) {
return http.authorizeExchange()
.pathMatchers("/actuator/**").permitAll()
.anyExchange().authenticated()
.and().build();
}
复制代码
如上的配置使得全部访问/actuator开头的URL都必须是登陆的状态。咱们还可使用更加细化的配置:
@Configuration
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.requestMatchers(EndpointRequest.to(ShutdownEndpoint.class))
.hasRole("ACTUATOR_ADMIN")
.requestMatchers(EndpointRequest.toAnyEndpoint())
.permitAll()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations())
.permitAll()
.antMatchers("/")
.permitAll()
.antMatchers("/**")
.authenticated()
.and()
.httpBasic();
}
}
复制代码
如上的配置主要实现了:
为了可以使用HTTP基自己份验证测试上述配置,能够添加默认的spring安全性用户:
spring:
security:
user:
name: actuator
password: actuator
roles: ACTUATOR_ADMIN
复制代码
与之前的版本同样,咱们能够轻松添加自定义指标。建立自定义健康端点的抽象保持不变。与Spring Boot 1.x不一样,endpoints.<id> .sensitive
属性已被删除。/health端点公开的运行情况信息取决于:
management.endpoint.health.show-details
复制代码
该属性可使用如下值之一进行配置:
management.endpoint.health.roles
配置。/health端点有不少自动配置的健康指示器:如redis、rabbitmq等组件。
management.health.mongo.enabled: false
复制代码
或者禁用全部自动配置的健康指示器:
management.health.defaults.enabled: false
复制代码
除此以外,还添加了新的接口ReactiveHealthIndicator
以实现响应式运行情况检查。
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
复制代码
@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() {
// we could use WebClient to check health reactively
return Mono.just(new Health.Builder().up().build());
}
}
复制代码
健康指标的一个便利功能是咱们能够将它们聚合为层次结构的一部分。 所以,按照上面的示例,咱们能够将全部下游服务分组到下游服务类别下。只要每一个嵌套服务均可以访问,这次访问就是健康的。
在Spring Boot 2.0中,有一个bean类型为MeterRegistry
将会被自动配置,而且MeterRegistry
已经包含在Actuator的依赖中。以下为咱们得到的/metrics端点信息。
{
"names": [
"jvm.gc.pause",
"jvm.buffer.memory.used",
"jvm.memory.used",
"jvm.buffer.count",
// ...
]
}
复制代码
能够看到,不一样于1.x,咱们已经看不到具体的指标信息,只是展现了一个指标列表。为了获取到某个指标的详细信息,咱们能够请求具体的指标信息,如/actuator/metrics/jvm.gc.pause
{
"name": "jvm.gc.pause",
"description": "Time spent in GC pause",
"baseUnit": "seconds",
"measurements": [{
"statistic": "COUNT",
"value": 2.0
}, {
"statistic": "TOTAL_TIME",
"value": 0.07300000000000001
}, {
"statistic": "MAX",
"value": 0.0
}],
"availableTags": [{
"tag": "cause",
"values": ["Metadata GC Threshold"]
}, {
"tag": "action",
"values": ["end of minor GC", "end of major GC"]
}]
}
复制代码
咱们能够看到,如今的指标要详细得多。不只包括不一样的值,还包括一些相关的元数据。
/info端点没有什么变化,咱们能够经过maven或者gradle引入依赖,增长git的详细信息。
<dependency>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
</dependency>
复制代码
一样的,咱们可使用maven和gradle的插件,获取到构建的name,group和version(须要类路径下存在META-INF/build-info.properties文件)。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
复制代码
咱们能够自定义端点,Spring Boot 2已经更新了自定义端点的方法,下面咱们定义一个能够查询、开启或者关闭features标志位的端点。
@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;
//...
}
}
复制代码
定义的端点路径由@Endpoint
中的id属性决定,在如上的例子中,请求的端点地址为/actuator/features
。并用以下的方法注解来定义操做:
启动应用,能够看到控制台多了以下的日志输出:
[...].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如何暴露咱们的端点,至于切换到Spring MVC,咱们只须要引入依赖便可,并不须要更改任何代码。
以前方法上的元数据信息(sensitive, enabled)都不在使用了,开启或禁用端点,使用@Endpoint(id = “features”, enableByDefault = false)
。相比于旧的读写模型,咱们可使用@DeleteOperation
定义DELETE操做。
咱们还能够经过注解@EndpointExtension
扩展事先定义好的端点,更精确的注解为:@EndpointWebExtension
,@EndpointJmxExtension
。
@Component
@EndpointWebExtension(endpoint = InfoEndpoint.class)
public class InfoWebEndpointExtension {
private InfoEndpoint delegate;
@Autowired
public InfoWebEndpointExtension(InfoEndpoint delegate) {
this.delegate = 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) {
// return 5xx if this is a snapshot
return 200;
}
}
复制代码
本文主要讲了Actuator 2.x相关特性和使用,对比了与Actuator 1.x 在使用上的区别。Actuator 2.x不依赖于某个框架组件(如Spring MVC),作到了易于插拔和扩展。当咱们想要切换到Webflux时,经过Actuator 2.x中的适配器,不须要更改任何代码便可实现。 本文源码:github.com/keets2012/S…