# 基本介绍
# 监控的意义
- 监控服务状态是否宕机
- 监控服务运行指标(内存、虚拟机、线程、请求等)
- 监控日志
- 管理服务(服务下线)
# 可视化监控平台
Spring Boot Admin 开源社区项目,是一个针对spring-boot的actuator接口进行UI美化封装的监控工具,客户端注册到服务端后,通过Http请求方式,服务端定期从客户端获取对应的信息,Health信息、内存信息、JVM信息、垃圾回收信息、各种配置信息(比如数据源、缓存列表和命中率)等,还可以直接修改logger的level。
# 如何使用
- 导入依赖坐标
<properties>
<spring-boot-admin.version>2.7.10</spring-boot-admin.version>
</properties>
<!-- Admin服务端 -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>${spring-boot-admin.version}</version>
</dependency>
<!--Admin客户端-->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin.version}</version>
</dependency>
注意
这里的spring-boot-admin.version要和springboot的版本相同
- 配置里面配置一下端口
spring:
boot:
admin:
client:
# 当前客户端将信息上传到哪个服务器上
url: http://localhost:8080
management:
endpoints:
web:
exposure:
include: '*' # 开放哪些监测信息
endpoint:
health:
show-details: ALWAYS # 开放健康信息
logfile:
external-file: ./logs/sys-console.log
- springboot启动类
@SpringBootApplication
@EnableAdminServer //设置启用Admin服务端
public class SpringbootActuatorServerApplication{
public static void main(String[] args){
SpringApplication.run(SpringbootActuatorServerApplication.class,args);
}
}
# 监控原理
监控中显示的信息实际上是通过发送请求后得到json数据,然后展示出来。按照上述操作,可以发送更多的以/actuator开头的链接地址,获取更多的数据,这些数据汇总到一起组成了监控平台显示的所有数据。
Actuator,可以称为端点,描述了一组监控信息,SpringBootAdmin提供了多个内置端点,通过访问端点就可以获取对应的监控信息,也可以根据需要自定义端点信息。通过发送请求路劲/actuator可以访问应用所有端点信息,如果端点中还有明细信息可以发送请求/actuator/端点名称来获取详细信息。
地址 | 描述 |
---|---|
/beans | 显示所有的Spring bean列表 |
/caches | 显示所有的缓存相关信息 |
/scheduledtasks | 显示所有的定时任务相关信息 |
/loggers | 显示所有的日志相关信息 |
/configprops | 显示所有的配置信息 |
/env | 显示所有的环境变量信息 |
/mappings | 显示所有控制器相关信息 |
/info | 显示自定义用户信息配置 |
/metrics | 显示应用指标相关信息 |
/health | 显示健康检查状态信息,up表示成功 down表示失败 |
/threaddump | 显示程序线程的信息 |
- springboot admin设置了13个较为常用的端点作为默认开放的端点,如果需要控制默认开放的端点的开放状态,可以通过配置设置,如下:
management:
endpoints:
enabled-by-default: true # 是否开启默认端点,默认值true
- 整体上来说,对于端点的配置有两组信息,一组是endpoints开头的,对所有端点进行配置,一组是endpoint开头的,对具体端点进行配置
management:
endpoint: # 具体端点的配置
health:
show-details: always
info:
enabled: true
endpoints: # 全部端点的配置
web:
exposure:
include: "*"
enabled-by-default: true
# 自定义监控指标
端点描述了被监控的信息,除了系统默认的指标,还可以自行添加显示的指标
# INFO端点
info端点描述了当前应用的基本信息,可以通过两种形式快速配置info端点的信息
- 在yml文件中通过设置info节点的信息就可以快速配置端点信息
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
info:
enabled: true
info: #配置info信息
env:
enabled: true
info:
enabled: true
company: 千舜网络
author: sylone
- 编程形式,通过配置的形式只能添加固定的数据,此信息与配置信息共存
@Component
public class InfoConfig implements InfoContributor {
@Override
public void contribute(Info.Builder builder) {
builder.withDetail("runTime",System.currentTimeMillis());//添加单个信息
Map infoMap = new HashMap();
infoMap.put("buildTime","2006");
builder.withDetails(infoMap);//添加一组信息
}
}
# Health端点
health端点描述当前应用的运行健康指标,即应用的运行是否成功
@Component
public class HealthConfig extends AbstractHealthIndicator {
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
boolean condition = true;
if(condition) {
builder.status(Status.UP);//设置运行状态为启动状态
builder.withDetail("runTime", System.currentTimeMillis());
Map infoMap = new HashMap();
infoMap.put("buildTime", "2006");
builder.withDetails(infoMap);
}else{
builder.status(Status.OUT_OF_SERVICE);//设置运行状态为不在服务状态
builder.withDetail("上线了吗?","你做梦");
}
}
}
# Metrics端点
metrics端点描述了性能指标,除了系统自带的监控性能指标
@Service
public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {
@Autowired
private BookDao bookDao;
private Counter counter;
public BookServiceImpl(MeterRegistry meterRegistry){
counter = meterRegistry.counter("用户付费操作次数:");
}
@Override
public boolean delete(Integer id) {
//每次执行删除业务等同于执行了付费业务
counter.increment();
return bookDao.deleteById(id) > 0;
}
}
# 自定义端点
可以根据业务需要自定义端点,方便业务监控
@Component
@Endpoint(id="pay",enableByDefault = true)
public class PayEndpoint {
@ReadOperation
public Object getPay(){
Map payMap = new HashMap();
payMap.put("level 1","300");
payMap.put("level 2","291");
payMap.put("level 3","666");
return payMap;
}
}
由于此端点数据spirng boot admin无法预知该如何展示,所以通过界面无法看到此数据
可以通过HTTP请求获取当前端点的信息,但是需要先开启当前端点对外功能,或者设置当前端点为默认开发的端点
# 集成Nacos
在使用Admin时,如果没有注册中心,需要各个客户端填写Admin服务端地址,而Admin是支持Nacos、Eureka、ZooKeeper等组件,可以直接从注册中心拉取服务实例
- 添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
- 项目yml配置添加nacos地址,包含客户端和服务端
spring:
application:
# 应用名称
name: ruoyi-xxxx
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
# 登录认证
- 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- 配置spring 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;
@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
.headers().frameOptions().disable()
.and().authorizeRequests()
.antMatchers(adminContextPath + "/assets/**"
, adminContextPath + "/login"
, adminContextPath + "/actuator/**"
, adminContextPath + "/instances/**"
).permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage(adminContextPath + "/login")
.successHandler(successHandler).and()
.logout().logoutUrl(adminContextPath + "/logout")
.and()
.httpBasic().and()
.csrf()
.disable();
}
}
- 在ruoyi-monitor-dev.yml配置用户,默认账户ruoyi/123456
spring:
security:
user:
name: ruoyi
password: 123456
boot:
admin:
ui:
title: 若依服务状态监控
# 日志相关
- Spring Boot Admin提供了基于Web页面的方式实时查看日志,前提是服务中配置了logging.file.name
logging:
file:
name: logs/${spring.application.name}/info.log
- 进入日志->日志文件查看实时日志
- 进入日志->日志配置动态修改日志级别
# 自定义通知
可以通过添加实现Notifier接口的Spring Beans来添加您自己的通知程序
import org.springframework.stereotype.Component;
import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
import de.codecentric.boot.admin.server.domain.events.InstanceEvent;
import de.codecentric.boot.admin.server.domain.events.InstanceStatusChangedEvent;
import de.codecentric.boot.admin.server.notify.AbstractStatusChangeNotifier;
import reactor.core.publisher.Mono;
/**
* 通知发送配置
*
* @author ruoyi
*/
@Component
public class RuoYiStatusChangeNotifier extends AbstractStatusChangeNotifier
{
public RuoYiStatusChangeNotifier(InstanceRepository repository)
{
super(repository);
}
@Override
protected Mono<Void> doNotify(InstanceEvent event,
de.codecentric.boot.admin.server.domain.entities.Instance instance)
{
return Mono.fromRunnable(() -> {
if (event instanceof InstanceStatusChangedEvent)
{
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:
break;
}
}
});
}
}