1. 前言
生产上对
Web
应用 的监控是十分必要的。我们可以近乎实时来对应用的健康、性能等其他指标进行监控来及时应对一些突发情况。避免一些故障的发生。对于
Spring Boot
应用来说我们可以通过一个轻量级的监控工具
Spring Boot Admin (SBA)
来进行监控。
2. Spring Boot Admin
Spring Boot Admin
是由德国软件工程师
Johannes Edmeier
开源的用于管理和监控
Spring Boot
应用程序。已经被收纳入
Spring Initializr
截至发文时间的最新正式版本为
2.1.6
,快照为
2.2.0-SNAPSHOT
。
C/S
架构风格 。 应用程序作为
Spring Boot Admin Client
向
Spring Boot Admin Server
注册(通过
HTTP
)或使用
Spring Cloud
注册中心(如
Eureka
,
Consul
)发现。SERVER程序采用了 响应式Web框架
Spring Webflux
。 展示UI采用了
Vue.js
,展示Spring Boot Admin Client 通过
Spring Boot Actuator
端点上的一些监控。常见的功能或者监控如下:
- 显示健康状况
-
显示应用度量指标详情,例如
- JVM和内存指标
- micrometer 度量
- 数据源指标
- 缓存指标
- 显示构建信息编号
- 关注并下载日志文件
-
下载
heapdump
-
查看
jvm
系统和环境属性 - 查看 Spring Boot 配置属性
- 支持 Spring Cloud 的环境端点和刷新端点
- 支持 K8s
- 易用的日志级别管理
-
与
JMX-beans
交互 - 查看线程转储
-
查看
http
跟踪 -
查看
auditevents
-
查看
http-endpoints
- 查看计划任务
- 查看和删除活动会话(使用 Spring Session )
-
查看
Flyway
/Liquibase
数据库迁移 - 状态变更通知(通过电子邮件,Slack,Hipchat等,支持钉钉)
- 状态更改的事件日志(非持久化)
3. 快速集成
接下来让我们来在
Spring Boot
项目中集成
Spring Boot Admin
。注意版本的兼容性,可通过
Spring Initializr
来验证。
3.1 配置 Spring Boot Admin Server
Spring Boot Admin Server
一般推荐独立作为一个
Spring Boot
jar
应用运行。 只需要将下列依赖添加到你的
pom.xml
中:
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 生产需要保证监控的安全性-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>复制代码
然后通过添加
@EnableAdminServer
到配置中来引入
Spring Boot Admin Server
配置:
@EnableAdminServer
@SpringBootApplication
public class SpringBootAdminApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAdminApplication.class, args);
}
}复制代码
3.2 配置 Spring Boot Admin
每个要注册的应用程序都必须包括
Spring Boot Admin Client
。为了保护端点,你还应该添加安全依赖
spring-boot-starter-security
。
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>复制代码
然后在客户端应用程序的
application.yml
中增加以下配置:
spring:
boot:
admin:
client:
# Spring Boot Admin Server 地址 http://localhost:8080 可自定义
url: http://localhost:8080
# 默认情况下,大多数端点都不通过http公开,我们公开了所有端点。对于生产,您应该仔细选择要公开的端点。
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: ALWAYS复制代码
分别启动
SBA
服务端和客户端 。打开服务端页面
http://localhost:8080
将进入以下监控界面:
进而也可以获取
admin-client
的具体监控指标:
如果您已经将
Spring Cloud Discovery
(
eureka
、
consul
等)用于您的应用程序,则不需要
Spring Boot Admin
客户端。只需将
DiscoveryClient
添加到
Spring Boot Admin Server
,其余的事情通过自动配置完成,可通过官方示例来查看。
4. Spring Boot Admin 安全访问控制
应用的监控指标都是极其敏感的数据。所以生产上必须增加安全访问控制以避免发生泄漏事件。你可以使用你擅长的安全框架来做访问控制。这里我们采用 Spring Security 来保护我们的 Spring Boot Admin 。
4.1 保护 Spring Boot Admin Server 服务器
添加 Spring Security Starter 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>复制代码
设置管理账户信息
spring:
security:
user:
name: SBA_admin
password: SBA_password
roles: SBA_ADMIN复制代码
配置安全路径访问控制
package cn.felord.admin.server.configuer;
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import java.util.UUID;
/**
* The type Security secure config.
*
* @author Felordcn
* @since 2019 /10/19 23:33
*/
@Configuration
public class AdminServerSecurityConfig extends WebSecurityConfigurerAdapter {
private final AdminServerProperties adminServer;
/**
* Instantiates a new Security secure config.
*
* @param adminServer the admin server
*/
public AdminServerSecurityConfig(AdminServerProperties adminServer) {
this.adminServer = adminServer;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
final String adminServerContextPath = this.adminServer.getContextPath();
successHandler.setDefaultTargetUrl(adminServerContextPath+"/");
http.authorizeRequests()
.antMatchers(adminServerContextPath + "/assets/**").permitAll() // <1>
.antMatchers(adminServerContextPath + "/login").permitAll()
.anyRequest().authenticated() // <2>
.and()
.formLogin().loginPage(adminServerContextPath + "/login").successHandler(successHandler).and() // <3>
.logout().logoutUrl(adminServerContextPath + "/logout").and()
.httpBasic().and() // <4>
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // <5>
.ignoringRequestMatchers(
new AntPathRequestMatcher(adminServerContextPath + "/instances", HttpMethod.POST.toString()), // <6>
new AntPathRequestMatcher(adminServerContextPath + "/instances/*", HttpMethod.DELETE.toString()), // <6>
new AntPathRequestMatcher(adminServerContextPath + "/actuator/**") // <7>
)
.and()
.rememberMe().key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600);
}
}复制代码