Spring Boot 有一个非常好用的监控和管理的源软件,这个软件就是 Spring Boot Admin。该软件能够将 Actuator 中的信息进行界面化的展示,也可以监控所有 Spring Boot 应用的健康状况,提供实时警报功能。
主要的功能点有:
可点击https://github.com/codecentric/spring-boot-admin更多了解 Spring-boot-admin。
搭建服务流程说明
**版本说明:**版本建议:SpringBoot2.x=SpringBootAdmin2.x(比如SpringBoot2.3.x可以用SpringBootAdmin2.3.x)
创建一个 Spring Boot 项目,用于展示各个服务中的监控信息,加上 Spring Boot Admin 的依赖,具体代码如下所示
org.springframework.boot
spring-boot-starter-parent
2.3.6.RELEASE
1.8
2.2.5.RELEASE
2.3.6.RELEASE
Hoxton.SR8
2.3.1
org.springframework.boot
spring-boot-starter-web
de.codecentric
spring-boot-admin-starter-server
${admin.starter.server.version}
添加 @EnableAdminServer
@EnableAdminServer
@SpringBootApplication
public class AdminServerApplication {
public static void main(String[] args) {
SpringApplication.run(AdminServerApplication.class,args);
}
}
在属性文件中增加端口配置信息:
server:
port: 8000
spring:
application:
## 注册服务名
name: admin-order
management:
endpoint:
health:
show-details: always
启动程序,访问 Web 地址 http://127.0.0.1:8000/ 就可以看到主页面了,这个时候是没有数据的,如图 1 所示
流程
创建 amdin-order 服务,将服务注册到 admin-server 中
org.springframework.boot
spring-boot-starter-parent
2.3.6.RELEASE
1.8
2.2.5.RELEASE
2.3.6.RELEASE
Hoxton.SR8
2.3.1
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.projectlombok
lombok
1.16.14
provided
de.codecentric
spring-boot-admin-starter-client
${spring.boot.admin.client.version}
spring:
application:
## 注册服务名
name: admin-order
## spring boot admin
boot:
admin:
client:
api-path:
url: http://127.0.0.1:8000
instance:
prefer-ip: true #?使用ip注册进来
server:
port: 8100
# ?endpoints config
management:
endpoint:
health:
show-details: always
endpoints:
enabled-by-default: true
web:
base-path: /actuator
exposure:
include: '*'
@SpringBootApplication
public class AdminOrderApp {
public static void main(String[] args) {
SpringApplication.run(AdminOrderApp.class,args);
}
}
从新刷新 admin 平台,admin-order 服务就可以监控
自定义的 Info 信息、健康状态、元数据,如图
客户端需要把日志同步ADMI服务中,通过JMX,客户端配置如下
${CONSOLE_LOG_PATTERN}
${log.path}/debug.log
${log.path}/%d{yyyy-MM, aux}/debug.%d{yyyy-MM-dd}.%i.log.gz
50MB
30
%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n
${log.path}/error.log
${log.path}/%d{yyyy-MM}/error.%d{yyyy-MM-dd}.%i.log.gz
50MB
30
%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n
ERROR
management:
endpoints:
web:
exposure:
include: '*'
enabled-by-default: true
endpoint:
health:
show-details: ALWAYS
# 日志记录
logfile:
external-file: D:/project/springcould-alibaba-example/logs/admin-order/debug.log
从新打 Admin 监控平台,点击 admin-order 服务查看日志,如下
@Slf4j
@RestController
public class OrderController {
@GetMapping("getOrder")
public String getOrder() {
log.info("getOrder.execute");
Date date = new Date();
// SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(date);
log.info("getOrder.resp 记录当前时间:普通时间: {}", time);
return "admin order cliect hello";
}
}
访问 http://127.0.0.1:8100/getOrder 查看日志文件
日志文件等级配置
org.springframework.boot
spring-boot-starter-security
@Configuration(proxyBeanMethods = false)
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" );
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();
}
}
spring:
security:
user:
name: "admin"
password: "admin"
客户端注册 admin 服务需要配置 username 和 password
spring:
application:
## 注册服务名
name: admin-order
## spring boot admin
boot:
admin:
client:
api-path:
url: http://127.0.0.1:8000
instance:
prefer-ip: true #?使用ip注册进来
username: admin
password: admin
不懂 Nacos 怎样作为注册中心,可以查看 Spring Cloud Alibaba 微服务组件 Nacos 注册中心(三)
org.springframework.boot
spring-boot-starter-parent
2.3.6.RELEASE
1.8
2.2.5.RELEASE
2.3.6.RELEASE
Hoxton.SR8
2.3.1
org.springframework.boot
spring-boot-starter-web
de.codecentric
spring-boot-admin-starter-server
${admin.starter.server.version}
org.springframework.boot
spring-boot-starter-security
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.cloud
spring-cloud-dependencies
${spring.cloud.version}
pom
import
com.alibaba.cloud
spring-cloud-alibaba-dependencies
${spring.cloud.alibaba.version}
pom
import
group: ADMIN 作为一组监控服务,服务端可以拉取客户端配置为 group:ADMIN
spring:
application:
## 注册服务名
name: admin-server
security:
user:
name: "admin"
password: "admin"
cloud:
nacos:
## 注册中心地址
discovery:
server-addr: 127.0.0.1:8848
group: ADMIN
客户端同服务端配置 (也要从新注册到 Nacos 服务)
org.springframework.boot
spring-boot-starter-mail
spring:
mail:
host: smtp.qq.com #?发件人使用的qq邮箱服务
username: [email protected]
#?授权码,不是密码,在qq邮箱设置‐账号里面有生成授权码
password: zaydkxfjbjwbbgbc
boot:
admin:
notify:
mail:
#?发件人
from: [email protected]
#?收件人,多个中间用,分隔
to: [email protected]
/**
* 自定义 dicator
* @date: 2021/12/15 17:31
*/
@Component
public class MyHealthIndicator implements HealthIndicator {
@Override
public Health health() {
int errorCode = check(); //?perform?some?specific?health?check
if (errorCode != 0) {
return Health.down().
withDetail("msg","error service").
withDetail("code",500).
build();
}
return Health.up().build();
}
private int check() {
return 0;
}
}
/**
* 自定义 info
* @date: 2021/12/16 18:53
*/
@Component
public class AppInfo implements InfoContributor {
@Override
public void contribute(Info.Builder builder) {
builder.withDetail("version","1.0.RELEASE");
builder.withDetail("project","admin-order");
}
}
yml 配置
info:
appName: admin-order
mavenAppName: '@project.artifactId@'
mavenVersion: '@project.version@'
ADMIN 控制台查看
SpringBootActuator为Micrometer提供了依赖管理和自动配置功能,Micrometer是一个应用指标facade(面门),支持多种监控系统,包括:
AppOptics,AzureMonitor,NetflixAtlas,CloudWatch,Datadog,Dynatrace,Elastic,Ganglia,Graphite,Humio,Influx/Telegraf,JMX,KairosDB,NewRelic,Prometheus,SignalFx,GoogleStackdriver,StatsD,和Wavefront。
JVM度量,报告利用率(JVMmetrics,reportutilizationof):
各种内存和缓冲池(Variousmemoryandbufferpools)
与垃圾收集有关的统计数据(Statisticsrelatedtogarbagecollection)
线程利用率(Threadsutilization)
加载/卸载的类数(Numberofclassesloaded/unloaded)
@RestController
public class HelloController {
@GetMapping("/sayHi")
public String sayHi(String productNo) throws InterruptedException {
// 线程长请求
//Thread.sleep(5000);
// 定制基于Metrics的计数器
Metrics.counter("order.counter","productNo",productNo).increment();
// 定制基于Metrics的定时器
Timer timer = Metrics.timer("order.timer");
timer.record(()->{
System.out.println("success");
});
// 定制基于Metrics的仪表 记录单个值 一般集合数量
Metrics.gauge("order.gauge",1);
// 定制基于Metrics的摘要 一般用来记录 百分比数值(缓存命中率)
DistributionSummary summary = Metrics.summary("redis.hitRate");
summary.record(1.5);
return "success";
}
}
增加定制 Metrics
Counter 是一种比较简单的Meter,它是一种单值的度量类型,或者说是一个单值计数器。
使用场景:
Counter 的作用是记录XXX的总量或者计数值,适用于一些增长类型的统计,例如下单、支付次数、Http请求总量记录等等
// 定制基于Metrics的计数器
Metrics.counter("order.counter","produntNo",produntNo).increment();
测试
127.0.0.1:8100/actuator/metrics/order.counter
{"name":"order.counter","description":null,"baseUnit":null,"measurements":[{"statistic":"COUNT","value":3.0}],"availableTags":[{"tag":"productNo","values":["G122390"]}]}
Timer(计时器)适用于记录耗时比较短的事件的执行时间,通过时间分布展示事件的序列和发生频率。
使用场景:
根据个人经验和实践,总结如下:
记录指定方法的执行时间用于展示。
记录一些任务的执行时间,从而确定某些数据来源的速率,例如消息队列消息的消费速率等。
// 定制基于Metrics的定时器
Timer timer = Metrics.timer(“xushu.timer”);
timer.record(()->{
System.out.println(“success”);
});
Summary
Summary(摘要)主要用于跟踪事件的分布,在Micrometer中,对应的类是DistributionSummary(分发摘要)。它的使用方式和Timer
十分相似,但是它的记录值并不依赖于时间单位。
使用场景:
根据个人经验和实践,总结如下:
不依赖于时间单位的记录值的测量,例如服务器有效负载值,缓存的命中率等。
// 定制基于Metrics的摘要 一般用来记录 百分比数值(缓存命中率)
DistributionSummary summary = Metrics.summary(“redis.hitRate”);
summary.record(1.5);