1.SpringBoot Admin介绍
生产上对 Web 应用 的监控是十分必要的。我们可以近乎实时来对应用的健康、性能等其他指标进行监控来及时应对一些突发情况。避免一些故障的发生。对于 Spring Boot 应用来说我们可以通过一个轻量级的监控工具 Spring Boot Admin (SBA) 来进行监控。
2.快速搭建
2.1 SpringBoot Admin Server
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
yml
server:
port: 8888
spring:
application:
name: admin-server
启动类
@EnableAdminServer
@SpringBootApplication
public class AdminServerApplication {
public static void main(String[] args) {
SpringApplication.run(AdminServerApplication.class, args);
}
}
2.2 SpringBoot Admin Client
pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.1.2</version>
</dependency>
yml
spring:
application:
name: admin-client
boot:
admin:
client:
url: http://localhost:8888 # 连接Admin Serve地址
server:
port: 9999
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
# 只有设置了该属性, SBA才会有日志控制面板
logging:
file:
name: D:/logs/output.log # 地址指向logback中的输出的日志文件
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="APP_Name" value="adminTest"/>
<contextName>${APP_Name}</contextName>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径,请根据需求配置路径-->
<property name="LOG_HOME" value="D:/logs"/>
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="adminTest >> ${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(LN:%L){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d [%thread][%X{traceId}] %-5p [%c] [%F:%L] - %msg%n</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/output.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/output-%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
</encoder>
</appender>
<!-- 日志输出级别,注意:如果不写<appender-ref ref="FILE" /> ,将导致springboot Admin找不到文件,无法查看日志 -->
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
输入 http://localhost:8888 就可以访问 admin 监控后台, 如果需要安全相关配置, 可以接入 Spring Security, 就可以解决安全性问题.
通过上面的搭建, 我们可以初步了解到SBA的功能和作用, 在此基础上, 我们还可以接入 TraceId 来保证全链路日志
3. 全链路日志
@Slf4j
public class TraceUtils {
private static final String TRACE_ID = "traceId";
public static void createTraceId() {
String traceId = MDC.get(TRACE_ID);
if (StringUtils.isBlank(traceId)) {
traceId = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
log.debug("create traceId :{}", traceId);
MDC.put(TRACE_ID, traceId);
}
}
public static void destroyTraceId() {
MDC.remove(TRACE_ID);
}
}
public class TraceIdInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
TraceUtils.createTraceId();
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
TraceUtils.destroyTraceId();
}
}
@Component
public class OpenFeignRequestInterceptor implements RequestInterceptor {
private static final String TRACE_ID = "traceId";
@Override
public void apply(RequestTemplate requestTemplate) {
String traceId = MDC.get(TRACE_ID);
requestTemplate.header(TRACE_ID, traceId);
}
}
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TraceIdInterceptor()).addPathPatterns("/**");
}
}
需要在所有服务中均加上这种上述代码(可以封装到Starter中), 即可实现 TraceId 全链路传递, 但是这种方式有部分弊端, 如果在子线程或线程池中进行RPC调用, 这种情况TraceId就会丢失, 这个问题也可以解决, 后续文章输出相应的解决方案.
4. 总结
今天主要介绍使用 Spring Boot Admin 对 Spring Boot 应用进行监控。 这里需要说明的是对一些小型应用 Spring Boot Admin 可以完全胜任监控功能,也非常简单好用。 但是对于大型分布式集群应用来说我个人不建议使用 Spring Boot Admin ,需要其它更加专业的 APM 监控,比如开源的 Apache Skywalking 、Prometheus + Grafana 等等, 收费的有阿里云ARMS企业级应用监控。