微服务的核心思想就是拆分业务,将单个系统按业务边界切分为多个可独立部署的微服务子系统。这样可以让系统更容易扩展,更快速的迭代,但必然会导致系统内服务实例数量的大量增加,再加上服务实例可能部署到不同的操作系统和网段,对整个系统进行管理和监控的难度比单系统环境要高出不少。幸运的是,针对Spring Boot技术体系我们有一个开箱即用的系统监控解决方案——Spring Boot Admin,对于中小规模的微服务系统,它几乎可以提供一切必要的监控需求,而且更重要的是它对于业务系统是非侵入性的,只需要几行配置就可以将一个基于Spring Boot技术开发的应用纳入到监控之中。
Spring Boot Admin分为两部分:client和server。client为被监控端,通过集成Spring Boot Actuator组件暴露出各种监控指标和信息,并注册到一个server端;server端接受client的注册,并定时查询client端提供的监控信息,管理员可以通过server端内置的一个web应用查看client的各项指标和信息。
现在我们就来利用Spring Boot Admin来为Spring Cloud Demo项目加入服务指标监控的功能。首先来创建一个monitor模块,作为Spring Boot Admin的server端,在pom.xml中加入如下配置:
de.codecentric
spring-boot-admin-starter-server
2.2.2
org.springframework.boot
spring-boot-starter-web
项目启动类中需要加入一个@EnableAdminServer的注解:
@SpringBootApplication
@EnableAdminServer
public class MonitorApplication {
public static void main(String[] args) {
SpringApplication.run(MonitorApplication.class, args);
}
}
application.yml配置文件只需要加入consul的相关配置即可,用于寻找其它被监控的client。Spring Boot Admin的客户端有两种注册方式,第一种是在被监控的服务客户端直接引入spring-boot-admin-starter-client,并配置server端的监控地址,主动向server端进行注册,这种一般用于监控独立的应用;第二种就是和Spring Cloud体系相匹配的,通过服务注册中心直接寻找需要被监控的客户端信息,在我们的demo里面就是consul,在consul中注册了的服务会直接成为Spring Boot Admin的client。
这样的话,我们demo里面的服务提供方只需要做很小的改造即可接入Spring Boot Admin的监控体系。主要就是加入Spring Boot Actuator支持,通过该框架来暴露出各种监控指标的,这样server端才能够对监控指标进行汇总和图形化展示。demo的parent项目之前已经添加了Spring Boot Actuator的依赖,但是默认只会暴露出一个/actuator/heath的接口,这对我们的监控来说是远远不够的,所以还需要在每个服务提供方暴露出更多的监控指标。具体来说,就是在配置文件中加入以下Actuator的配置:
#输出监控指标用于服务监控,暴露的监控指标可根据实际情况调整
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
#如果要在Spring boot admin中查看日志,需要指定存储的文件
logging:
file: ./logs/order-service.log
现在将服务全部启动,访问monitor的地址http://localhost:9010,就可以看到Spring boot admin的监控页面了:
需要注意的是,Spring Boot Admin完全依赖Actuator暴露的接口进行监控,如果没有实现这些接口,默认就会显示离线(比如consul实例实际上是在线的)。进入到具体的某个服务,可以看到更多的监控指标,还能够在线查看日志和修改logger的日志级别:
Spring Boot Admin还支持对标题和UI进行部分的定制,具体的配置项,可参考官方文档
monitor模块可以收集到应用的一些敏感信息,如果需要暴露到外网进行查看,就必须添加相关的安全措施。我们可以通过spring security框架,快速为server端添加相应的用户登录验证功能。首先在monitor中加入spring security的依赖:
org.springframework.boot
spring-boot-starter-security
然后编写一个Spring Security的配置类,验证规则可根据实际情况进行修改:
@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
private final String adminContextPath;
public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
this.adminContextPath = adminServerProperties.getContextPath();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
successHandler.setDefaultTargetUrl(adminContextPath + "/");
http.authorizeRequests()
.antMatchers(adminContextPath + "/assets/**").permitAll()
.antMatchers(adminContextPath + "/login").permitAll()
.antMatchers(adminContextPath + "/actuator/health").permitAll()
.anyRequest().authenticated()
.and()
//login登录页是spring boot admin ui里面已经集成了的
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
.logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers(
adminContextPath + "/instances",
adminContextPath + "/actuator/**"
);
}
}
重新启动后,再次访问monitor模块,就需要进行登录验证了:
登录的用户名和密码可以在application.yml中配置:
spring:
#允许登录监控系统的用户名和密码
security:
user:
name: admin
password: 123456
需要注意的是,如果没有使用注册中心,而是通过spring-boot-admin-starter-client的方式直接向server端注册的client,还需要加入server端的验证信息才能成功注册,类似像这样:
spring
boot:
admin:
client:
#server端的注册地址
url: http://localhost:9010
username: admin
password: 123456
instance:
#client的访问地址前缀,server通过该地址获取监控信息
service-base-url: http://192.168.1.252:8090
本文的相关代码可以查看这里 spring-cloud-demo