欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Boot微服务项目实战(第2版)学习笔记-第15章Spring Boot应用监控

程序员文章站 2022-05-08 10:57:45
...

本章主要介绍如何通过Spring Boot监控和管理应用、自定义监控端点以及自定义HealthIndicator等内容。

1.应用监控介绍

Spring Boot大部分模块都是用于开发业务功能或者连接外部资源。除此之外,Spring Boot还提供了spring-boot-starter-actuator模块,该模块主要用于管理和监控应用,它是一个用于暴露自身信息的模块,可以有效地减少监控系统在采集应用指标时的开发量。

spring-boot-starter-actuator模块提供了监控和管理端点以及一些常用的扩展和配置方式,具体如表所示。

Spring Boot微服务项目实战(第2版)学习笔记-第15章Spring Boot应用监控

2.使用监控

2.1 引入依赖

在Spring Boot中使用监控,首先需要在pom.xml文件中引入所需的依赖spring-boot-starter-actuator,具体代码如下:

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

2.2 添加配置

在pom.xml文件引入spring-boot-starter-actuator依赖包之后,需要在application.properties文件中添加如下的配置信息:

### 应用监控配置
# 指定访问这些监控方法的端口
management.server.port=8080
  • management.server.port:用于指定访问这些监控方法的端口。

2.3 测试

spring-boot-starter-actuator依赖和配置都添加成功之后,重新启动spring-boot-book-v2项目,项目启动成功之后,在浏览器中输入http://localhost:8080/actuator,可以看到如图所示的输出信息。

Spring Boot微服务项目实战(第2版)学习笔记-第15章Spring Boot应用监控

从图中可以看出,actuator只暴露了3个简单的endpoint,并且只有/health接口的内容还有点用,可以检查应用服务是否健康。当然,actuator绝对不止这么点功能,只是出于安全考虑,其余的endpoint默认被禁用了。在浏览器中输入:http://localhost:8080/actuator/health,可以看到应用的健康信息,“UP”代表应用是健康状态。

为了简单起见,我们来开启所有的接口。只需要在application.properties文件中加入一行配置即可:

### 开启所有的端点
management.endpoints.web.exposure.include=*

重新在浏览器中输入http://localhost:8080/actuator,便可以看到所有的endpoint,如图所示。

Spring Boot微服务项目实战(第2版)学习笔记-第15章Spring Boot应用监控

对于不带任何参数的读取操作,端点自动缓存对其响应。要配置端点缓存响应的时间,请使用cache.time-live属性,以下示例将beans端点缓存的生存时间设置为10秒:

默认情况下,端点通过使用端点的ID在/actuator路径下的HTTP上公开,例如,beans端点暴露在/actuator/beans下。如果要将端点映射到其他路径,则可以使用management.endpoints.web.path-mapping属性。另外,如果想更改基本路径,则可以使用management.endpoints.web.base-path。以下示例将/actuator/health重新映射到/healthcheck:

management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.health=healthcheck

要配置单个端点的启用,请使用management.endpoint.<id>.enabled属性,以下示例启用了shutdown端点:

management.endpoint.shutdown.enabled= true

另外,可以通过management.endpoints.enabled-by-default来修改全局端口的默认配置,以下示例启用info端点并禁用所有其他端点:

management.endpoints.enabled-by-default=false
management.endpoints.info.enabled=true

其他端点测试,可以按照表所示的访问路径依次访问测试。

Spring Boot微服务项目实战(第2版)学习笔记-第15章Spring Boot应用监控

在浏览器中可以把返回的数据格式化成json格式,这是因为在Google浏览器中安装了JsonView插件,具体安装步骤如下:

  1. 浏览器中输入链接:https://github.com/search?utf8=%E2%9C%93&q=jsonview,在弹出的页面中单击gildas-lormeau/JSONView-for-Chrome,如图所示。
Spring Boot微服务项目实战(第2版)学习笔记-第15章Spring Boot应用监控
  1. 单击【Download Zip】,插件下载完成,解压缩到相应目录中(D:\Download\JSONView-for-Chrome-master)。
  2. 在浏览器右上角单击【更多工具】→【扩展程序】→【加载已解压的扩展程序】。选择插件目录(D:\Download\JSONView-for-Chrome-master\WebContent)。
  3. 安装完成后,重新启动浏览器(快捷键Ctrl+R)。

3.自定义端点

3.1 自定义端点EndPoint

spring-boot-starter-actuator模块中已经提供了许多原生端点。根据端点的作用,我们可以把原生端点分为以下3大类。

  • 应用配置类:获取应用程序中加载的应用配置、环境变量、自动化配置报告等与Spring Boot应用密切相关的配置类信息。
  • 度量指标类:获取应用程序运行过程中用于监控的度量指标,比如内存信息、线程池信息、HTTP请求统计等。
  • 操作控制类:提供了对应用的关闭等操作类功能。

如果spring-boot-starter-actuator模块提供的这些原生端点无法满足需求,还可以自定义端点,自定义端点时,只要继承抽象类AbstractEndpoint即可。这里在spring-boot-book-v2目录/src/main/java/com.example.demo下新建actuator包,在actuator包下新建自定义端点类AyUserEndPoint,AyUserEndPoint主要用来监控数据库用户信息情况,比如用户总数量、被删除用户数量、活跃用户数量等。自定义端点AyUserEndPoint类的代码如下:

@Component
@Endpointid="userEndPoints")
public class AyUserEndpoint {
	@Resource
	private AyUserService ayUserService;
	@ReadOperation
	public Map<String, Object> invoke(){
		Map<String,Object> map = new HashMap<String, Object>();
		//当前时间
		map.put("current_time",new Date());
		//用户总数量
		map.put("user_num", ayUserService.findUserTotalNum());
		return map;
	}
}
  • @Endpoint(id=“userEndPoints”):@Endpoint注解简化了创建用户自定义端点的过程,@Endpoint相当于@WebEndpoint和@JmxEndpoint的整合,Web和jmx方式都支持。
  • @WebEndpoint:只会生成Web的方式的端点监控。
  • @JmxEndpoint:只会生成Jmx的方式监控。

在AyUserEndPoint类中,我们注入AyUserService接口,并在invoke方法中调用findUserTotalNum方法,查询当前数据库总的用户数。所以需要在AyUserService接口中添加方法findUserTotalNum,具体代码如下:

//查询用户数量
Long findUserTotalNum();

同时,在AyUserServiceImpl类中实现方法findUserTotalNum,具体代码如下:

@Override
public Long findUserTotalNum(){
	return ayUserRepository.count();
}

AyUserService类与AyUserServiceImpl类开发完成之后,就可以在invoke方法中使用。在invoke方法中定义Map集合,并向Map集合存放当前时间current_time和数据库用户总数user_num。

3.2 测试

代码开发完成之后,重启启动spring-boot-book-v2项目,在浏览器中输入访问地址:http://localhost:8080/actuator/userEndPoints,便可以看到请求到数据,具体数据如下:

{"user_num" : 3, "current":1512817762910}

从返回数据中,可以看出当前数据库总共有3个用户,以及当前具体时间(毫秒)。

3.3 自定义HealthIndicator

默认端点Health的信息是从HealthIndicator的bean中收集的,Spring中内置了一些HealthIndicator,如表所示。

Spring Boot微服务项目实战(第2版)学习笔记-第15章Spring Boot应用监控

启动项目spring-boot-book-v2,在浏览器中输入访问链接:http://localhost:8080/actuator/health,可以看到返回的Spring Boot应用健康数据只有:

{
	"status":"UP"
}

如果想要查看详细的应用健康信息,需要添加以下配置:

management.endpoint.health.show-details=always

配置完成之后,再次访问http://localhost:8080/actuator/health,获取的信息如下:

Spring Boot微服务项目实战(第2版)学习笔记-第15章Spring Boot应用监控

从上面的信息中,可以方便地查看目前应用所依赖资源(Redis、MongoDB)的运行情况及其他信息。

Tips:management.endpoint.health.show-details的值除了always之外还有when-authorized、never,默认值是never。

如果想要自定义符合自己业务需求的检查健康,需要自定义HealthIndicator来获得更多应用健康的信息。在spring-boot-book-v2项目目录/src/main/java/com.example.actuator下新建MyHealthIndicator类,该类实现HealthIndicator接口并重写health方法,MyHealthIndicator类具体代码如下:

@Component
public class MyHealthIndicator implements HealthIndicator{
	@Override
	public Health health(){
		Long totalSpace = checkTocalSpace();
		Long free checkFree();
		String status= checkstatus();
		checkFree();
		return new Health.Builder()
				.up()
				.withDetail("status", status)
				.withDetail("total", totalSpace)
				.withDetail("free", free)
				.build();
	}
	private String checkStatus(){
		//结合真实项目,获取相关参数
		return "Up";
	}
	private Long checkTocalSpace(){
		//结合真实项目,获取相关参数
		return 10000L;
	}
	private Long checkFree (){
		//结合真实项目,获取相关参数
		return 5000L;
	}
}

3.4 测试

代码开发完成之后,重新启动spring-boot-book-v2项目,项目启动成功之后,在浏览器中输入访问链接:http://localhost:8080/actuator/health,可以获得自定义健康类MyHealthIndicator返回的结果,具体结果信息如下:

my: {
	status:"UP",
	total: 10000,
	free: 5000
}
//忽略其他健康数据

从上面返回的json结果信息可以看出,json结果信息的key:my,也就是英文MyHealthIndicator去掉HealthIndicator。如果自定义健康类取名为MyDefineHealthIndicator,则返回结果信息将会变成:

myDefine: {
	status:"UP",
	total: 10000,
	free: 5000
}
//忽略其他健康数据

一般情况下,不会直接实现 HealthIndicator接口,而是继承AbstractHealthIndicator抽象类。因此,我们只需要重写doHealthCheck方法,并在这个方法中关注具体的健康检测的业务逻辑服务即可。

4.保护Actuator端点

Actuator端点发布的信息很多都涉及敏感信息和高危操作。比如/shutdown端点,它可以直接关闭应用程序,如果随便某个人都有权限访问该端点,那是非常危险的。因此,有必要控制Actuator端点的访问权限以避免Actuator端点被非法访问。想要保护Actuator端点,可以使用保护其他URL路径一样的方式,通过使用Spring Security来控制URL路径的授权访问。

在第14章中,我们已经在Spring Boot中集成了Spring Security,并且开发了WebSecurityConfig配置类对用户登录进行授权访问,现在我们改造该类,具体代码如下:

@Configuration
@EnableWebSecurity
public class WebsecurityConfig extends WebSecurityConfigurerAdapter {
	//省略代码
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//路由策略和访问权限的简单配置
		http
			.authorizeRequests()
			//要求有管理员的权限
			
			//登录失败返回URL:/loginerror.antMatchers("/shutdown").access("hasRole('ADMIN')")
			//登录成功跳转URL,这里跳转到用户首页
			//登录页面全部权限可访问
			.antMatchers("/**").permitAll()
			.and() 
			.formLogin() 
			//启用默认登录页面 
			.failureUrl("/login?error")
			.defaultSuccessUrl("/ayUser/test") 
			.permitAll(); 
		super.configure(http);
	}
}

通过使用antMatchers("/shutdown").access(“hasRole(‘READER’)”)方法,对/shutdown进行授权访问,/shutdown端点现在仅允许拥有ADMIN权限的用户进行访问。

端点/shutdown已经被保护起来了,假如现在想保护其他端点,例如/metrics、/health等,只需要为antMatchers()传入输入参数即可。具体代码如下:

.authorizeRequests()
//要求有管理员的权限
.antMatchers("/shutdown","/metrics","/health").access("hasRole('READER')")

如果觉得每次添加一个端点的访问权限都得在antMatchers()方法中修改很麻烦,可以在application.properties配置文件中配置端点访问的上下文,具体配置如下:

### 配置端点访问的上下文路径
management.endpoints.web.base-path=/manage

此时,在为Actuator端点赋予ADMIN权限限制的时候就能借助这个上下文/manage:

//要求有管理员的权限
.antMatchers("/manage/**").access("hasRole('READER')")