目录
Spring Boot Admin简介
快速开始
创建Spring Boot Admin Client
集成spring security
上测试环境
上UAT环境
项目demo地址
Spring Boot Admin简介
Spring Boot Admin是一个开源社区项目,用于管理和监控SpringBoot应用程序。 应用程序作为Spring Boot Admin Client向为Spring Boot Admin Server注册(通过HTTP)或使用SpringCloud注册中心(例如Eureka,Nacos)发现。 UI是的Vue.js应用程序,展示Spring Boot Admin Client的Actuator端点上的一些监控。常见的功能如下:
- 显示健康状况
- 显示详细信息,例如
- JVM和内存指标
- micrometer.io指标
- 数据源指标
- 缓存指标
- 显示内部信息
- 关注并下载日志文件
- 查看JVM系统和环境属性
- 查看Spring Boot配置属性
- 支持Spring Cloud的可发布/ env-和// refresh-endpoint
- 轻松的日志级别管理
- 与JMX-beans交互
- 查看线程转储
- 查看http-traces
- 查看审核事件
- 查看http端点
- 查看预定的任务
- 查看和删除活动会话(使用spring-session)
- 查看Flyway / Liquibase数据库迁移
- 下载heapdump
- 状态更改通知(通过电子邮件,Slack,Hipchat等)
- 状态更改的事件日志(非持久性)
Git地址:https://github.com/codecentric/spring-boot-admin
文档地址:https://codecentric.github.io/spring-boot-admin/2.1.6/#getting-started
快速开始
创建Spring Boot Admin Server
本案例使用的SpringBoot版本为2.1.7.RELEASE,SpringCloud的版本为Greenwich.RELEASE,SpringBoot Admin的版本为2.1.5,Nacos的版本为2.1.0.RELEASE,具体依赖请参照正文pom文件。
1.新建一个SpringBoot项目,选择加入Spring Boot Admin(Server)依赖(File->New->Project->Spring Initializr->配置jdk->Next->设置项目名称和路径->Next->勾选Spring Boot Admin(Server)->Finish)
2.加依赖(本文是通过Nacos做服务发现,所以需要加入SpringCloud和Nacos和actuator健康检查依赖)
<spring-boot-admin.version>2.1.5</spring-boot-admin.version>
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
<!--健康检查-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--Nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-dependencies</artifactId>
<version>${spring-boot-admin.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3.加注解(在启动类上SpringBootAdminApplication加@EnableAdminServer注解,开启AdminServer的功能)
@SpringBootApplication
@EnableAdminServer
public class SpringBootAdminApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAdminApplication.class, args);
}
}
4.写配置(在yml文件中配置nacos地址,开启actuator全部端点,配置日志打印路径)
server:
port: 8002
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.1.36:8848
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
# 日志
logging:
file: /application/applogs/admin.log
这样SpringBoot Admin Server就创建好了
创建Spring Boot Admin Client
本文的Client就是需要监控的服务,只需要将需要监控的服务注册到Nacos并且做如下配置即可
1.加入健康检查依赖(不打开admin无法检测到需要监控服务的信息)
<!--健康检查-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.打开健康检查全部端点(不配置admin只能监控一部分信息,线上请根据实际情况配置端点,防止产生安全问题)
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
3.配置日志输出地址(不配置无法在线查看打印日志)
logging:
file: /application/applogs/admin.log
访问地址http://localhost:8002,即可看到如下界面
查看监控信息
查看日志和动态调整日志级别
更多功能请自行了解
注意:
很多时候项目由于模块比较多,通常会配置servlet的context-path属性增加一节路径加以区分不同服务,如下
server:
port: 8005
servlet:
context-path: /activity
这时候actuator访问路径就是http://ip:port/activity/actuator SpringBoot Admin是没法识别到的,actuator默认访问的还是http://ip:port/actuator,这时候需要我们进行配置management的context-path属性,如下
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.1.36:8848
metadata:
management:
context-path: ${server.servlet.context-path}/actuator
配置后进入页面即可正常监控
到此Spring Boot Admin搭建已经完毕,但是这样岂不是大家都能访问,有句歌词唱的好(我家大门常打开,隔壁老王都能来。。。),给门加个锁把。
集成spring security
官方说明:
由于有多种方法可以解决分布式Web应用程序中的身份验证和授权,因此Spring Boot Admin不会提供默认方法。默认情况下
spring-boot-admin-server-ui
提供登录页面和注销按钮。
我们这里采用spring security提供安全保障,在Spring Boot Admin Server中统一配置
1.加依赖(由于涉及到前端页面所以需要web依赖)
<!--权限-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--Web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.写配置(配置security账号密码,服务注册时带上metadata-map信息),上面yml配置修改为如下配置
server:
port: 8002
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.1.36:8848
metadata:
user.name: "admin"
user.password: "admin!@#123"
security:
user:
name: "admin"
password: "admin!@#123"
boot:
admin:
context-path: "control"
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
# 日志
logging:
file: /application/applogs/admin.log
3.编写Security的配置文件
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;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
/**
* @author will
*/
@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","/css/**","/js/**","/image/*").permitAll()
//其他所有请求需要登录
.anyRequest().authenticated()
.and()
//登录页面配置,用于替换security默认页面
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
//登出页面配置,用于替换security默认页面
.logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers(
"/instances",
"/actuator/**"
);
}
}
启动项目,访问地址http://localhost:8002,即可看到登录页面
输入配置的账号密码登录,能看到注册的服务即可
页面还是比较炫酷的
上测试环境
令人激动的时刻到了,毕竟前面的努力马上就要转换成慢慢的成就感了,本以为jar包发给公司运维部署下就能通过域名访问了,但是理想和现实毕竟是有差距的,果然出问题了。。。
1.访问部署好的SpringBoot Admin服务,前端页面样式全部失效,浏览器F12查看发现下图
访问接口没有问题
css,js等静态资源获取不到,原因是域名全部变成了ip地址(nginx proxy_pass配置的名字)
看到这种情况应该是nginx反向代理出了问题,问了运维要了nginx的配置文件,如下,是的 被运维坑了,nginx缺少配置
解决:
在nginx配置文件你这个服务的proxy_pass下面增加 proxy_set_header Host $http_host; 配置即可解决(nginx修改配置文件即时生效命令,检查:nginx -t ,重载:nginx -s reload),
最后发现,其余的服务运维都有加这个配置,就我这个服务没有加(最后邀请他陪我共度的通宵)
上UAT环境
uat环境是https的环境,测试环境是http环境,看到这你应该若有所思,是的叒 双 又出问题了!!!
1.请求地址是https,静态资源访问的地址却是http,报错信息:Mixed Content: The page at 'https://XXX/control/login?logout' was loaded over HTTPS, but requested an insecure stylesheet 'http://XXX/control/assets/css/chunk-common.6aba055e.css'. This request has been blocked; the content must be served over HTTPS.
解决:
在nginx配置文件如图位置增加 add_header Content-Security-Policy "upgrade-insecure-requests;connect-src *";
2.登录进去之后SpringBoot Admin applications接口报401,并且提示跨域
解决:
1.在nginx配置文件的proxy_pass下面增加 proxy_set_header X-Forwarded-Proto https;";
2.在SpringAdmin Server服务中增加解决跨域的代码
import org.apache.catalina.valves.RemoteIpValve;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* @author will
*/
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS")
.allowedHeaders("origin", "content-type", "accept", "x-requested-with")
.maxAge(3600);
}
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
List<String> list = new ArrayList<>();
list.add("*");
corsConfiguration.setAllowedOrigins(list);
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
@Bean
public TomcatServletWebServerFactory servletContainer(){
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory ();
factory.setUriEncoding(Charset.forName("UTF-8"));
RemoteIpValve value = new RemoteIpValve();
value.setRemoteIpHeader("X-Forwarded-For");
value.setProtocolHeader("X-Forwarded-Proto");
value.setProtocolHeaderHttpsValue("https");
factory.addEngineValves(value);
return factory;
}
}
在次访问Https地址,成功!!!
项目demo地址
地址:https://gitee.com/liuyuzhijia/spring-boot-admin