Server端
引入依赖
<dependencies>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
yml配置
server:
port: 9000
servlet:
context-path: /monitor
spring:
application:
name: server
security:
user:
name: admin
password: 123456
management:
health:
redis:
enabled: false
endpoint:
health:
show-details: always
启动类
@EnableAdminServer
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
public class ServerApplication {
public static void main(String[] args){
SpringApplication.run(ServerApplication.class);
}
}
配置
访问、登录配置
@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
//项目应用路径
private final String adminContextPath;
public WebSecurityConfigurer(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()
.anyRequest().authenticated()
.and()
//登录和登出路径
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
.logout().logoutUrl(adminContextPath + "/logout").and()
//开启http basic支持,admin-client注册时需要使用
.httpBasic().and()
.csrf()
//开启基于cookie的csrf保护
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
//忽略这些路径的csrf保护以便admin-client注册
.ignoringAntMatchers(
adminContextPath + "/instances",
adminContextPath + "/actuator/**"
);
}
}
注入额外的请求头,方便客户端区分请求来源
@Component
public class HttpHeadersProviderConfig implements HttpHeadersProvider {
@Value("${monitor.custom}")
private String custom;
@Override
public HttpHeaders getHeaders(Instance instance) {
HttpHeaders httpHeaders = new HttpHeaders();
//设置约定好的请求头参数
httpHeaders.add("spring-boot-admin-service", custom);
return httpHeaders;
}
}
监控实例状态
@Component
public class CustomNotifierConfig extends AbstractStatusChangeNotifier {
public CustomNotifierConfig(InstanceRepository repository) {
super(repository);
}
@Override
protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
return Mono.fromRunnable(() -> {
if (event instanceof InstanceStatusChangedEvent) {
System.out.println("实例名称:"+instance.getRegistration().getName());
System.out.println("实例服务地址:"+instance.getRegistration().getServiceUrl());
String status = ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus();
switch (status) {
case "DOWN":
System.out.println("健康检查没通过!");
break;
case "OFFLINE":
System.out.println("服务离线!");
break;
case "UP":
System.out.println("服务上线!");
break;
case "UNKNOWN":
System.out.println("服务未知异常!");
break;
default:
System.out.println(status);
break;
}
}
});
}
}
client
引入依赖
<dependencies>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.1.4</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-logging</artifactId>
</dependency>
</dependencies>
yml配置
management:
health:
redis:
enabled: false
endpoint:
shutdown:
enabled: true
health:
show-details: always
logfile:
external-file: /opt/logs/client.log #生成的日志地址
enabled: true
endpoints:
enabled-by-default: true
web:
exposure:
include: '*'
spring:
application:
name: client
boot:
admin:
client:
url: http://127.0.0.1:9000/monitor #server请求地址
username: admin #server用户名
password: 123456 #server密码
logging:
config: classpath:config/log.xml
启动类
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
public class ClientApplication {
public static void main(String[] args){
SpringApplication.run(ClientApplication.class);
}
}
Actuator过滤配置,防止非服务端请求actutor
@WebFilter
@ServletComponentScan
@Component
public class ActuatorFilter implements Filter {
@Value("${monitor.custom:9001}")
private String adminServicePort;//和服务端的monitor.custom必须一致,服务端请求才能通过,日志等相关功能才能正常获取,并过滤掉非服务端的异常请求
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
//判断约定好的请求头参数
if (request.getRequestURI().contains("/actuator") && !adminServicePort.equals(request.getHeader("spring-boot-admin-service"))){
throw new RuntimeException("抱歉,你无权限访问,Actuator端口受保护! Sorry, you have no permission to access it,Actuator port protected!");
}
filterChain.doFilter(servletRequest, servletResponse);
}
}
部署完成
输入服务端定义的账号密码,登录成功
实例列表
日志查看