原文参考:https://dzone.com/articles/spring-boot-actuator-in-spring-boot-20
Spring Boot Actuator提供了一些actuator endpoint来实现对你的应用程序进行监控和交互,当然,你也可以创建自定义的enpoint.在接下来的部分,我们会创建一个简单的程序,完成以下功能:
使Actuator endpoints 提供程序的git版本信息,jdk版本信息,
对 enpoint的访问增加安全校验
创建一个自定义的endpoint
一、创建project
环境:spring boot 2.0+,java8,maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
为了让这个例子看起来有点功能,我们创建一个简单的RestController
@RestController
public class HelloActuatorController {
@RequestMapping(value = "/helloactuator", method= GET)
public String helloActuator() {
return "Hello Spring Boot Actuator";
}
}
启动程序,在浏览器输入http://localhost:8080/helloactuator,将会看到"Hello Spring boot Actuator"
二、Spring提供的Endpoint
有了上面的准备,现在,在浏览器输入http://localhost:8080/actuator 就可以看到spring actuator默认提供了哪些内容,返回的内容可以看到Actuator endpoints的大概情况,如果我们需要添加自定义的endpoint时,需要避免命名的冲突。
如上所示,只能看到3个Actuator enpdoinds.为了展示更多的endpoints,需要在application.properties(application.yml)中增加include或exclude的配置,为了能显示所有的endpoints,配置如下
重启应用,这时除了shutdown endpoint之外的Actuator endpoints都是可以使用的。这些endpoints可以参考https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html
三、以info endpoint为例,增加代码的git版本信息
在pom.xml 中添加如下配置
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>2.2.4</version>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
<prefix>git</prefix>
<verbose>false</verbose>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
<format>properties</format>
<gitDescribe>
<skip>false</skip>
<always>false</always>
<dirty>-dirty</dirty>
</gitDescribe>
</configuration>
</plugin>
maven build之后,会发现在target/classes下多了一个git.properties.
接下来重新启动程序,访问http://localhost:8080/actuator
{
"git": {
"branch": "master",
"commit": {
"id": "d7d7202",
"time": "2018-03-24T13:24:51Z"
}
}
}
上面显示的信息只有git.properties的一部分,如果想要显示所有的信息,可以在application.properties上增加下面的配置,就可以看到所有的信息了
management.info.git.mode=full
四、增加Build信息
和增加git 版本信息的方式一样,我的来增加maven build的信息,只要在项目的META-INFO目录下存在build-info.properties文件,info endpoint就会将build信息显示出来,那怎样产生build-info文件呢?
需要引用spring-boot-maven-plugin插件
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
重新启动程序,可以看到下面的build 信息
{
"git": {...}, // 7 items
"build": {
"artifact": "myspringactuatorplanet",
"name": "myspringactuatorplanet",
"time": "2018-03-24T13:40:03.907109600Z",
"version": "0.0.1-SNAPSHOT",
"group": "com.mydeveloperplanet"
}
}
大部分的时候,我们并不希望这些信息被每个人都能访问到,所以需要对endpoind的增加安全校验,为了达到这个目的,首先,需要在pom.xml文件中增加Spring Security的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
添加了上面的依赖之后,重新启动程序在浏览器上访问8080端口的请求,在第一次访问的时候会弹出一个用户登陆的页面,用户名user,密码默认情况下是一串随机码,并在每次启动程序后都会更新,并打印在springboot的启动日志上
Using generated security password: 8da882c3-4bbb-4e71-88c2-13399d9f0724
可见默认的安全校验是对所有的http请求有效的,那现在假设我们只想用户验证的方式只作用于部分endpoint上,比如对springboot自带的endpoint起作用,而我们自定义的helloactuator不起作用,该怎么做呢?
根据spring的文档,我们需要新增一个配置类
@Configuration
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}
现在,只有Actuator endpoints需要验证了,这里需要提醒的是,上面的配置只作用于Actuator endpoints,我原以为EndpointRequest.toAnyEndpoint包含http://localhost:8080/actuator.但其实不是的,因为它并没有被当做是一个真正的endpoint。这个问题在springboot早已经存在,详细信息可以参考https://github.com/spring-projects/spring-boot/issues/12353.
现在的密码是每次启动springboot的时候自动生成的,可以通过增加userDetaisServise来避免,当然这种操作只是为了演示的方便,请不要适用到生产环境中。
@Bean
@Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user);
}
现在Actuator endpoints就可以通过username=user password=password进行访问了。
五、关于Health Endpoint
在默认情况下Health endpoint不会显示详细信息,这些信息通过spring自带的healthindicators进行解析收集,但默认情况下我们只能看到下面的数据。
{
"status": "UP"
}
为了能展示自带的healthindicators所收集的信息,需要在application.properties增加如下的配置,这样,所有通过healthindicators生成的信息都能被展示出来。
management.endpoint.health.show-details=when-authorized
这个值默认为never,表示不会展示任何health indicators收集的信息,现在设为when-authorized,让有权限的用户访问时显示health信息。
重新运行程序,访问请求http://localhost:8080/actuator/health 将会看到下面的信息
{
"status": "UP",
"details": {
"diskSpace": {
"status": "UP",
"details": {
"total": 408943587328,
"free": 75006865408,
"threshold": 10485760
}
}
}
}
我们也可以创建自定义的health indicators来展示软件的更多信息。创建自定义的health indicators需要实现HealthIndicator接口,下面的例子,我们将会检查当请求触发时,系统时间的分钟数是奇数还是偶数,这样我们可以很容易的测试health indicator状态的改变,当分钟数为偶数的时候,indicator返回UP状态,如果是奇数返回DOWN状态。所以,我们自定义类OddOrEvenMinuteHealthCheck的代码如下所示。
@Component
public class OddOrEvenMinuteHealthIndicator implements HealthIndicator {
@Override
public Health health() {
int errorCode = 0;
LocalTime now = LocalTime.now();
if (now.getMinute() % 2 != 0) {
errorCode = 1;
}
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build();
}
return Health.up().build();
}
}
重新启动springboot,访问http://localhost:8080/actuator/health,将会多出下面的信息
"oddOrEvenMinute": {
"status": "UP"
},
在一个分钟数为奇数的时间点访问,这时status变为DOWN
"oddOrEvenMinute": {
"status": "DOWN",
"details": {
"Error Code": 1
}
},
HeathIndicator提供的状态DOWN,OUT_OF_SERVICE,UP,UNKNOWN,我们也可以增加我们自定义的状态码,比如,我们可以增加ODD和EVEN状态,只要在新增的状态码加到application.properties中,如下所以
management.health.status.order=DOWN, OUT_OF_SERVICE, UNKNOWN, ODD, EVEN, UP
最后,需要在OddOrEvenMinuteHealthCheck修改对应的状态即可
if (errorCode != 0) {
return Health.status("ODD").withDetail("Error Code", errorCode).build();
}
return Health.status("EVEN").build();
六、总结
这篇文章,我们对spring actuator进行了了解,知道怎么样启用Actuator endpoints,如果增加git 版本信息和maven构建信息到info actuator endpoint,以及如何给endpoint增加安全加校验,最后,如何给health enpoint自定义一个health indicators.