前言
上一章说了spring boot admin管理spring boot应用,但是没有权限认证,邮件通知,什么情况一个应用多实例(不推荐这种做法),就技术而言一个应用多个boot实例是会冲突的,需要配置解决冲突。
1. Securing Spring Boot Admin Server
在spring boot admin server端加入pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
增加配置即可
spring.security.user.name=feng spring.security.user.password=feng
这里是security的配置,使用HTTP管理(笔者为了区别properties,单独写了yml文件,方便切换)
spring.boot.admin.client:
url: http://localhost:8082
instance:
metadata:
user.name: ${spring.security.user.name}
user.password: ${spring.security.user.password}
而实际项目上估计是eureka等注册中心管理用户,Submitting the credentials using Eureka:
eureka.instance.metadata-map.user.name=${spring.security.user.name} eureka.instance.metadata-map.user.password=${spring.security.user.password}
注入用户与密码:参考https://codecentric.github.io/spring-boot-admin/2.2.1/#_securing_spring_boot_admin_server
增加过滤权限代码,拦截URL
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.context.annotation.Configuration;
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;
@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 {
// @formatter:off
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter( "redirectTo" );
http.authorizeRequests()
.antMatchers( adminContextPath + "/assets/**" ).permitAll()
.antMatchers( adminContextPath + "/login" ).permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage( adminContextPath + "/login" ).successHandler( successHandler ).and()
.logout().logoutUrl( adminContextPath + "/logout" ).and()
.httpBasic().and()
.csrf().disable();
// @formatter:on
}
}
用途如下,这里是官方的示例
访问:http://localhost:8082/
使用配置的账号登录
很明显这不符合多租户,权限控制的原则。需要深度定制
2. 邮件通知
在spring boot admin server端加入pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
在配置中加入
spring.mail.host=smtp.example.com
spring.mail.username=
spring.mail.password=
spring.boot.admin.notify.mail.to=admin@example.com
具体参数还可以参考:
Property name | Description | Default value |
---|---|---|
spring.boot.admin.notify.mail.enabled | Enable mail notifications |
|
spring.boot.admin.notify.mail.ignore-changes | Comma-delimited list of status changes to be ignored. Format: "<from-status>:<to-status>". Wildcards allowed. |
|
spring.boot.admin.notify.mail.template | Resource path to the Thymeleaf template used for rendering. |
|
spring.boot.admin.notify.mail.to | Comma-delimited list of mail recipients |
|
spring.boot.admin.notify.mail.cc | Comma-delimited list of carbon-copy recipients | |
spring.boot.admin.notify.mail.from | Mail sender |
|
spring.boot.admin.notify.mail.additional-properties | Additional properties which can be accessed from the template |
默认情况当Admin Server的监控对象上下线就会发送邮件,可以手动配置规则,比如堆内存超过4G,告警通知等;当然也可以自定义通知,通过继承AbstractEventNotifier
or AbstractStatusChangeNotifier。
3. 一个应用多个实例
我们把spring boot应用打成war包,一个Tomcat部署多个来模拟。
#server.port=8180 spring.application.name=BootClient
并将其中一个名称改为BootClient2,如果两个应用都配置了/或者相同的路径,需要加前缀以示区分
不同目录不存在问题
启动后,发现居然识别为2个应用,我明明是一个Tomcat服务啊,应该是一个应用2个实例
估计是注册中心的注册数算的
这里要说一下,我在旧项目(Spring Boot 1.5)这样启动会报错
Could not register MBean for endpoint [dumpEndpoint] org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [org.springframework.boot.actuate.endpoint.jmx.DataEndpointMBean@67e7c413] with key 'dumpEndpoint';
解决办法很多,比如关闭jmx,在application配置文件中配置
spring.jmx.enabled=false
Spring的JMX将Spring bean导出为模型MBean,这样就可以查看应用程序的内部情况,能够更改配置,包括应用的运行期,不建议关闭,建议配置域到jmx中
在application配置文件中配置
spring.jmx.default-domain=xxx #spring默认域配置 endpoints.jmx.domain=applicationname #client端点配置JMX域。
单独配置后就不会冲突了,然而在Spring Boot 2.2 居然修复了。
3.1 致命问题
以为这样就OK了,也都能显示,然而OUT了,
由于暴露的接口都是同一个应用的,我居然BOOTCLIENT实例在点击时跳转到BOOTCLIENT2实例了,显然接口接入混了,上报状态的路径与获取数据的接口都不正确,此时需要修改application配置,在此示例中ROOT的示例是正确的的路径没问题,无需修改;ROOT2需要,如果有其他实例仍然需要
修改ROOT2的application配置
#这是对eureka 的监控地址增加路径前缀,默认/actuator;这个坑笔者调试源码才发现的
eureka.instance.metadata-map.management.context-path=/ROOT2/actuator
#这是对暴露的/actuator接口增加前缀,表示接口的地址不是/,即不是ROOT应用
management.server.servlet.context-path=/ROOT2
修改后正常了
总结
其实spring boot admin官方有详细的说明文档,配置权限管理,通知;只是不能满足多租户的要求,一般的应用也足够了。业务多了也有足够的人力定制化。另外一个应用多个实例在旧项目居多,新项目大部分都推广微服务架构体系了,只是spring boot admin的监控在配置上比较麻烦,不注意就会监控失败,或者监控不正确。