Spring boot admin 服务监控利器

目录
  1. 1. 一、简介
  2. 2. 二、搭建
    1. 2.1. 1、服务端
      1. 2.1.1. 8、服务端配置
    2. 2.2. 2、客户端
      1. 2.2.1. 4、客户端配置
    3. 2.3. 3、微服务
      1. 2.3.1. 3.1、服务端
      2. 2.3.2. 3.2、客户端
    4. 2.4. 4、我的微服务预警发送其他服务状态信息思路
  3. 3. 三、问题处理
    1. 3.1. 1、logback按日期分割的日志如何查看
    2. 3.2. 2、邮件预警(修改监控平台配置)
    3. 3.3. 3、服务端和客户端不在同一个服务器(或者使用Docker)而导致的客户端实例都离线状态

一、简介

用于对 Spring Boot 应用的管理和监控。可以用来监控服务是否健康、是否在线、以及一些jvm数据等等。
Spring Boot Admin 分为服务端(spring-boot-admin-server)和客户端(spring-boot-admin-client),服务端和客户端之间采用 http 通讯方式实现数据交互;单体项目中需要整合 spring-boot-admin-client 才能让应用被监控。
在 SpringCloud 项目中,spring-boot-admin-server 是直接从注册中心抓取应用信息,不需要每个微服务应用整合 spring-boot-admin-client 就可以实现应用的管理和监控。

主要的功能点有:

  • 显示应用程序的监控状态
  • 应用程序上下线监控
  • 查看 JVM,线程信息
  • 可视化的查看日志以及下载日志文件
  • 动态切换日志级别
  • Http 请求信息跟踪

二、搭建

1、服务端

需先搭建服务端,监控服务,被监控的服务连接过来即可,开箱即用。

1、新建一个项目做为服务端
2、引入spring-boot-admin服务端依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  <!--用于检查系统的监控情况-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--Spring Boot Admin Server监控服务端-->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.7.10</version>
</dependency>
<!--增加安全防护,防止别人随便进-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

3、启动类上开启@EnableAdminServer

4、security安全防护配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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;

@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/**"
);
}
}

5、yml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
server:
port: 9111
spring:
boot:
admin:
ui:
title: HMB服务监控中心
client:
instance:
metadata:
tags:
environment: local
#要获取的client的端点信息
probed-endpoints: health,env,metrics,httptrace:trace,threaddump:dump,jolokia,info,logfile,refresh,flyway,liquibase,heapdump,loggers,auditevents
monitor: # 监控发送请求的超时时间
default-timeout: 20000
security: # 设置账号密码
user:
name: admin
password: admin
# 服务端点详细监控信息
management:
trace:
http:
enabled: true
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always

6、启动项目
访问 http://ip:端口,

如我的http://localhost:9111,账号密码都是admin(上面的security配的)

7、自定义服务状态变化后,提醒功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import de.codecentric.boot.admin.server.domain.entities.Instance;
import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
import de.codecentric.boot.admin.server.domain.events.InstanceEvent;
import de.codecentric.boot.admin.server.notify.AbstractStatusChangeNotifier;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

@Component
public class WarnNotifierConfig extends AbstractStatusChangeNotifier {
public WarnNotifierConfig(InstanceRepository repository) {
super(repository);
}

@Override
protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
// 服务名
String serviceName = instance.getRegistration().getName();
// 服务url
String serviceUrl = instance.getRegistration().getServiceUrl();
// 服务状态
String status = instance.getStatusInfo().getStatus();
// 详情
Map<String, Object> details = instance.getStatusInfo().getDetails();
// 当前服务掉线时间
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = simpleDateFormat.format(date);
// 拼接短信内容
StringBuilder str = new StringBuilder();
str.append("服务名:【" + serviceName + "】 \r\n");
str.append("服务状态:【"+ status +"】 \r\n");
str.append("地址:【" + serviceUrl + "】\r\n");
str.append("时间:" + format +"\r\n");

return Mono.fromRunnable(()->{
// 这里写你服务发生改变时,要提醒的方法
// 如服务掉线了,就发送短信告知
});
}
}

8、服务端配置

配置 默认参数 解释
spring.boot.admin.context-path / server端的访问路径
spring.boot.admin.monitor.status-interval 10,000ms 检查实例状态的时间间隔。
spring.boot.admin.monitor.status-lifetime 10,000ms client端状态的生命周期,该生命周期内不会更新client状态。单位是毫秒
spring.boot.admin.monitor.info-interval 1m 查询实例信息的时间间隔。
spring.boot.admin.monitor.info-lifetime 1m info的生命周期,该生命周期内不会更新info状态。
spring.boot.admin.monitor.default-timeout 10,000 发出请求时的默认超时。可以使用spring.boot.admin.monitor.timeout.*重写特定端点的单独值。
spring.boot.admin.monitor.timeout.* 每个endpointId超时的键值对。默认default-timeout
spring.boot.admin.monitor.default-retries 0 失败请求的默认重试次数。修改请求(PUT, POST, PATCH, DELETE)永远不会重试。可以使用spring.boot.admin.monitor.retries.*重写特定端点的单个值。
spring.boot.admin.monitor.retries.* 键值对,包含每个endpointId的重试次数。默认为default-retries。修改请求(PUT, POST, PATCH, DELETE)永远不会重试。
spring.boot.admin.metadata-keys-to-sanitize “.password “ , “ . ∗ s e c r e t “, “.*secret “,”.∗secret”, “.*key “ , “ . ∗ t o k e n “, “.*token “,”.∗token”, “.*credentials.”, “.*vcap_services$” 匹配这些regex模式的键的元数据值将在所有json输出中被清除。
spring.boot.admin.probed-endpoints “health”, “env”, “metrics”, “httptrace:trace”, “threaddump:dump”, “jolokia”, “info”, “logfile”, “refresh”, “flyway”, “liquibase”, “heapdump”, “loggers”, “auditevents” 要获取的client的端点信息
spring.boot.admin.instance-auth.enabled true 启用从Spring配置属性中提取凭证
spring.boot.admin.instance-auth.default-user-name null 用于验证注册服务的默认用户名。该spring.boot.admin.instance-auth.enabled属性必须为true。
spring.boot.admin.instance-auth.default-user-password null 用于验证注册服务的默认用户密码。该spring.boot.admin.instance-auth.enabled属性必须为true。
spring.boot.admin.instance-auth.service-map.*.user-name 用于使用指定名称对注册的服务进行身份验证的用户名。该spring.boot.admin.instance-auth.enabled属性必须为true。
spring.boot.admin.instance-auth.service-map.*.user-password 用户密码,用于使用指定名称对注册的服务进行身份验证。该spring.boot.admin.instance-auth.enabled属性必须为。
spring.boot.admin.instance-proxy.ignored-headers “Cookie”, “Set-Cookie”, “Authorization” 向客户提出请求时,不转发标题。
spring.boot.admin.ui.public-url <img src=“assets/img/icon-spring-boot-admin.svg”><\span>Spring Boot Admin </span > 用于在ui中构建基本href的基本URL。 如果在反向代理后面运行(使用路径重写),则可以用来进行正确的自我引用。如果省略主机/端口,将从请求中推断出来。
spring.boot.admin.ui.brand 要在导航栏中显示的品牌。
spring.boot.admin.ui.title “Spring Boot Admin” 要显示的页面标题。
spring.boot.admin.ui.login-icon “assets/img/icon-spring-boot-admin.svg” 在登录页面上用作图像的图标。
spring.boot.admin.ui.favicon “assets/img/favicon.png” 用作默认图标的图标,用于桌面通知的图标。
spring.boot.admin.ui.favicon-danger “assets/img/favicon-danger.png” 当一项或多项服务关闭并用作桌面通知时,用作收藏夹图标。
启用spring.boot.admin.ui.remember-me true 切换为在登录页面上显示/隐藏“记住我”复选框。
spring.boot.admin.ui.poll-timer.cache 2500 以毫秒为单位的轮询持续时间,以获取新的缓存数据。
spring.boot.admin.ui.poll-timer.datasource 2500 以毫秒为单位的轮询持续时间,以获取新的数据源数据。
spring.boot.admin.ui.poll-timer.gc 2500 以毫秒为单位的轮询持续时间,以获取新的gc数据。
spring.boot.admin.ui.poll-timer.process 2500 以毫秒为单位的轮询持续时间,以获取新的过程数据。
spring.boot.admin.ui.poll-timer.memory 2500 以毫秒为单位的轮询持续时间,以获取新的内存数据。
spring.boot.admin.ui.poll-timer.threads 2500 以毫秒为单位的轮询持续时间,以获取新的线程数据。

2、客户端

被监控的服务,需要连接服务端

1、依赖

1
2
3
4
5
6
7
8
9
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2、yml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
server:
port: 9222

spring:
application:
name: client
boot:
admin:
client: # spring-boot-admin 客户端配置
url: http://localhost:9111 #服务端连接地址
username: admin # 服务端账号
password: admin # 服务端密码
instance:
prefer-ip: true # 使用ip注册

# 服务端点详细监控信息
management:
# health: # 检测服务状态是通过http://localhost:9111/actuator/health接口,可去掉不用检测项
# mail: # 健康检测时,不要检测邮件
# enabled: false
trace:
http:
enabled: true
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
logfile: # 日志(想在线看日志才配)
enabled: true
external-file: ./logs/client-info.log # 日志所在路径

3、启动项目
此时客户端就已经注册进来了。

点击日志也可在线查看日志

此时,如果我们服务掉线了,就会触发服务端的预警功能,告知我们。

4、客户端配置

配置 默认值 解释
spring.boot.admin.client.enabled true 是否启用springbootAdmin客户端
spring.boot.admin.client.url 要注册的server端的url地址。如果要同时在多个server端口注册,则用逗号分隔各个server端的url地址
spring.boot.admin.client.api-path “instances” 管理服务器上注册端点的http路径。
spring.boot.admin.client.username, spring.boot.admin.client.password SBA Server api使用HTTP基本认证保护时使用的用户名和密码。
spring.boot.admin.client.period 10,000 重复注册的时间间隔(ms)。(client通过持续不断地向server端进行注册来保持client端与server端的连接)
spring.boot.admin.client.connect-timeout 5,000 连接注册超时时间(毫秒)。
spring.boot.admin.client.read-timeout 5,000 注册读取超时,单位是毫秒
spring.boot.admin.client.auto-registration true 若设置为true,则在应用就绪后自动调度注册应用的定时任务。
spring.boot.admin.client.auto-deregistration null 是否开启自动注销,如果服务端运行在云平台,默认值是true
spring.boot.admin.client.register-once true 如果设置为true,客户端将只注册一个管理服务器(按照spring.boot.admin.instance.url定义的顺序);如果该管理服务器宕机,将自动向下一个管理服务器注册。如果为false,将在所有管理服务器上注册。
spring.boot.admin.client.instance.health-url 根据management-url和endpoint .health.id 要注册的Health-url。在可达URL不同的情况下可以被重写(例如Docker)。在注册表中必须唯一。
spring.boot.admin.client.instance.management-base-url 根据management-base-url和management.context-path 要注册的Management-url。可被覆盖的情况下可达的url是不同的(例如Docker)。
spring.boot.admin.client.instance.service-base-url 根据主机名、server.port 用于计算service-url 的基本URL。该路径值在运行时进行获取并赋值给 base url。
spring.boot.admin.client.instance.service-url 根据service-base-url和server.context-path 要注册的Service-url。可被覆盖的情况下可达的url是不同的(例如Docker)。
spring.boot.admin.client.instance.service-path / 要注册的服务路径。在可达路径不同的情况下可以被重写(例如,以编程方式设置的上下文路径)。
spring.boot.admin.client.instance.name ${spring.application.name} 注册的服务名称,覆盖spring.application.name
spring.boot.admin.client.instance.prefer-ip false 在注册的url中使用ip地址而不是主机名。如果true,将使用ip:port。否则将使用InetAddress.getLocalHost()返回的IP地址。
spring.boot.admin.client.instance.metadata.* 与此实例关联的元数据键-值对。
spring.boot.admin.client.instance.metadata.tags.* 标记为与此实例关联的键-值对。

3、微服务

除特别说明外,都是在上面的基础上添加

3.1、服务端

1、添加依赖

1
2
3
4
5
6
<!--  nacos注册中心配置-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>

2、yml添加配置

1
2
3
4
5
6
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
# namespace: # 要和你的服务同一命名空间

3.2、客户端

客户端不用引spring-boot-admin-starter-clien依赖,springbootadmin会去服务列表里找

如果服务有配置context-path路径,则需添加yml配置

1
2
3
4
5
6
7
spring:
cloud:
nacos:
discovery:
metadata: # minitor监控的context-path配置
management:
context-path: ${server.servlet.context-path}/actuator

4、我的微服务预警发送其他服务状态信息思路

问题:由于该组件重写状态发生变化时的接口,没有提供其他服务的状态信息,只有本服务,但是如果是集群、多实例,我又想知道,该服务其他实例或者其他的服务状态信息,是否存活。

思路:我在发送预警之前,访问其他服务的检测健康接口,如:http://localhost:7050/attendance/actuator/nacos-discovery,有返回值,就可提取里面的信息,报错了说明没有该服务没有启动

结果展示:如我的预警内容,发送当前服务状态、当前服务剩余健康实例、其他健康服务数等等

三、问题处理

1、logback按日期分割的日志如何查看

修改logback-spring.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    <!-- 以下的大概意思是:1.先按日期存日志,日期变了,将前一天的日志文件名重命名为XXX%日期%索引,新的日志仍然是sys.log -->
<!-- 2.如果日期没有发生变化,但是当前日志的文件大小超过1KB时,对当前日志进行分割 重命名-->
<appender name="APP_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}</file> <!-- 主要是这一行!!! -->
<!-- rollingPolicy:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。 -->
<!-- 滚动策略,基于时间和占用空间大小来制定 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 文件名 log/app.log.2020-01-01.0.log -->
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i</fileNamePattern>
<!-- 活动文件的最大文件大小 500MB -->
<maxFileSize>500MB</maxFileSize>
<!-- 最长保存时间 10天 -->
<maxHistory>10</maxHistory>
<!-- 总大小5G -->
<totalSizeCap>5GB</totalSizeCap>
</rollingPolicy>
<encoder>
<!-- 日志格式 -->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
</configuration>

2、邮件预警(修改监控平台配置)

在服务的状态改变时,监控平台会发出预警邮件。

使用到的依赖是:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

需修改监控平台配置项如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
spring:
mail:
test-connection: true
username: xxxxxxx@126.com # 用于发件的邮箱
password: ****** # 邮箱的授权码
protocol: smtps # 发件邮箱的协议,根据运营商设置,smtp/smtps/pop3等等
host: smtp.126.com # 邮箱的host地址
port: 465 # 运营商给的端口
properties:
mail.debug: false
mail.smtp.auth: true
boot:
admin:
notify:
mail:
from: patr1ck@126.com # 用于发件的邮箱,需要与上面的保持一致
ignore-changes: UNKNOWN:UP # 忽略的状态变化,即从unkonwn变为up时不发送邮件
to: mawengang@cestc.cn # 接收的邮箱,如有多个使用逗号隔开。
template: classpath:/mail/status-changed.html # 模板地址,这里简单的修改成了中文,一般不用改变

由于国内腾讯云、阿里云默认封了 25 端口,若项目是部署在云服务器,使用上述的配置是无法正常发送邮件的,需要更改为使用 465 端口,并启用 SSL 邮件加密,最后系统防火墙别忘了开放 465 端口,配置示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
spring:
mail:
port: 465
protocol: smtp
host: smtp.qq.com
username: 158747124@qq.com
password: xxxxxxx
properties:
mail:
smtp:
auth: true
socketFactory:
port: 465
class: javax.net.ssl.SSLSocketFactory
ssl:
enable: true
starttls:
enable: true
required: true
boot:
admin:
notify:
mail:
to: 389723578@qq.com
from: 158747124@qq.com

以上配置,当已注册的服务的状态从 UP 变为 OFFLINE 或其他状态时,Admin Server 会自动将告警邮件发送到对应的邮箱,更多邮箱相关的配置示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
spring.mail.host=smtp.qq.com
spring.mail.username=xx@qq.com
spring.mail.password=xxxxxx

spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.ssl.enable=true
spring.mail.properties.mail.smtp.socket.factory.class=javax.net.ssl.SSLSocketFactory
spring.mail.properties.mail.smtp.socket.factory.fallback=false
spring.mail.properties.mail.smtp.port=465
spring.mail.properties.mail.transport.protocol=smtp

#需要忽略的状态改变通知,逗号分隔,例如不通知离线到上线的状态,则填写为OFFLINE:UP
#spring.boot.admin.notify.mail.ignore-changes=
#接收通知的邮箱地址,逗号分隔
spring.boot.admin.notify.mail.to=yangzhilong@qq.com
#需要抄送的邮箱地址,逗号分隔
#spring.boot.admin.notify.mail.cc=test1@qq.com
#邮件发送者,大部分情况与登录名相同
spring.boot.admin.notify.mail.from=${spring.mail.username}
#邮件主题,默认是:#{application.name} (#{application.id}) is #{to.status}
spring.boot.admin.notify.mail.subject=${spring.profiles.active} profile's #{application.name} (#{application.id}) is #{to.status}
#邮件内容,默认是:#{application.name} (#{application.id})\nstatus changed from #{from.status} to #{to.status}\n\n#{application.healthUrl}
spring.boot.admin.notify.mail.text=${spring.profiles.active} profile's #{application.name} (#{application.id})\nstatus changed from #{from.status} to #{to.status}
#Comma-delimited list of status changes to be ignored. Format: "<from-status>:<to-status>". Wildcards allowed.默认值:"UNKNOWN:UP"
#spring.boot.admin.notify.mail.ignore-changes=

3、服务端和客户端不在同一个服务器(或者使用Docker)而导致的客户端实例都离线状态

我把springbootAdmin的server端部署到了Linux系统服务器(服务器1),把要监控的项目部署到了另一台Linux服务器(服务器2),这两台服务器处于同一个局域网内。运行这两个项目,发现程序server端能够发现这个我的client项目,但是client项目一直处于断开状态。

客户端添加此配置即可:(service-url是客户端的URL)

1
spring.boot.admin.client.instance.service-url=http://192.168.0.2:8080

如果不想写死url的话,也可使用service-host-type配置:

1
spring.boot.admin.client.instance.service-host-type=ip

不过使用这种方式的时候,无法查看日志,提示:获取日志文件失败。不过点击【下载】按钮是可以下载的。

扩展阅读:Spring Boot Admin 基础使用教程