SpringBootAdmin2.0实现微服务应用监控

Spring Boot Admin 监控介绍

Spring Boot Admin是一个Web应用,用于管理和监视Spring Boot应用程序的运行状态。
每个Spring Boot应用程序都被视为客户端并注册到管理服务器。
背后的数据采集是由Spring Boot Actuator端点提供。

Spring Boot Admin 是由服务端和客户端组成

在 Spring Boot 项目中,Spring Boot Admin 作为 Server 端,其他的要被监控的应用作为 Client 端

Spring Boot Admin 设计目的

问题:在微服务生态中,由于一个项目中服务过多,导致排查问题等造成很大的困难。
目的:实时监控各个服务的健康状态,日志及时查看,服务异常及时通知人员进行修复等。

Spring Boot Admin 实现原理

1.所有需要被监控的服务,均加上SpringBoot提供的Actuator包
2.启动Admin Server端,作为注册中心,监控所有客户端当前状态(自己也需要被注册并且被监控)
3.启动Admin Clinet端,第一次主动向Admin Server端提供健康信息
4.Admin Server端定时轮询所有监控Admin Client端的节点及时获得最新信息
5.Admin Client端如果发生异常,Admin Server端提供了邮件功能等,及时通知用户进行修复

Spring Boot Admin 提供了哪些功能

  • 显示健康状况
  • 显示详细信息,例如
    • JVM和内存指标
    • micrometer.io指标
    • 数据源指标
    • 缓存指标
  • 显示内部编号
  • 关注并下载日志文件
  • 查看JVM系统和环境属性
  • 查看Spring Boot配置属性
  • 支持Spring Cloud的可发布/ env-和// refresh-endpoint
  • 轻松的日志级别管理
  • 与JMX-beans交互
  • 查看线程转储
  • 查看http跟踪
  • 查看审核事件
  • 查看http端点
  • 查看预定的任务
  • 查看和删除活动会话(使用spring-session)
  • 查看Flyway / Liquibase数据库迁移
  • 下载heapdump
  • 状态更改通知(通过电子邮件,Slack,Hipchat等)
  • 状态更改的事件日志(非持久性)

SpringBootAdmin2.0集成eureka

创建sunny-eureka-service

这是eureka-server端,注册中心。

pom文件

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

application.yml

配置应用名和端口信息,以及向sunny-admin-server-service注册的地址为http://localhost:8888,最后暴露自己的actuator的所有端口信息,具体配置如下:

#服务端口号
server:
  port: 8888

spring:
  application:
    name: sunny-eureka-service

eureka:
  instance:
    #为false时,那么注册到Eureka中的Ip地址就是本机的Ip地址
    prefer-ip-address: false
    #服务注册中心实例的主机名
    hostname: localhost
    health-check-url-path: /actuator/health
    status-page-url-path: /actuator/info
  client:
    # 表示是否从 eureka server 中获取注册信息(检索服务),默认是true
    fetch-registry: false
    # 表示是否将自己注册到 eureka server(向服务注册中心注册自己),默认是true
    register-with-eureka: false
    service-url:
      #服务注册中心的配置内容,指定服务注册中心的位置,eureka 服务器的地址(注意:地址最后面的 /eureka/ 这个是固定值)
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      #2、在原先的基础上添加security用户名和密码(例如:http://username:password@localhost:8000/eureka/)
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS #显示详细信息

启动类

@EnableEurekaServer
@SpringBootApplication
public class SpringBootApplicationEurekaServer {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplicationEurekaServer.class);
    }
}

创建sunny-admin-server-service

这是SpringBootAdmin Server端

pom文件

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
    </parent>

    <dependencies>
        <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>
        <!--如果spring-boot-starter-web 排除掉tomcat,则可以引入jetty-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>

        <!-- admin server -->
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-server</artifactId>
            <version>2.2.1</version>
        </dependency>

        <!-- eureka客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!-- 健康监控 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

application.yml

management.endpoints.web.exposure.include 配置,我这里的配置暴露的所有节点进行监控

server:
  port: 8889

spring:
  application:
    name: sunny-admin-server-service
    
eureka:
  instance:
    #服务注册中心实例的主机名
    hostname: localhost
    health-check-url-path: /actuator/health
    status-page-url-path: /actuator/info
  client:
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:8888/eureka/

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS #显示详细信息

启动类

启动类添加@EnableAdminServer注解,开启监控

@EnableDiscoveryClient
@SpringBootApplication
public class SpringBootApplicationMainAdminServer {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplicationMainAdminServer.class);
    }
}

创建sunny-admin-client-service

这是SpringBootAdmin Client端

pom文件

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

application.yml

server:
  port: 8183

spring:
  application:
    name: sunny-admin-client-service

eureka:
  instance:
    #服务注册中心实例的主机名
    hostname: localhost
    health-check-url-path: /actuator/health
    status-page-url-path: /actuator/info
  client:
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:8888/eureka/


management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS #显示详细信息

启动类

@EnableDiscoveryClient
@SpringBootApplication
public class SpringBootApplicationMainAdminClient {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplicationMainAdminClient.class);
    }

}

启动三个工程,在浏览器上输入localhost:8889 ,监控平台显示的界面如下:

Spring Boot Admin Server 可以监控的功能很多,使用起来没有难度,下面描述下可以监测的部分内容:

  • 应用运行状态,如时间、垃圾回收次数,线程数量,内存使用走势。
  • 应用性能监测,通过选择 JVM 或者 Tomcat 参数,查看当前数值。
  • 应用环境监测,查看系统环境变量,应用配置参数,自动配置参数。
  • 应用 bean 管理,查看 Spring Bean ,并且可以查看是否单例。
  • 应用计划任务,查看应用的计划任务列表。
  • 应用日志管理,动态更改日志级别,查看日志。
  • 应用 JVM 管理,查看当前线程运行情况,dump 内存堆栈信息。
  • 应用映射管理,查看应用接口调用方法、返回类型、处理类等信息。

SpringBootAdmin2.0集成eureka+securty认证

Web应用程序中的身份验证和授权有多种方法,因此Spring Boot Admin不提供默认方法。默认情况下,spring-boot-admin-server-ui提供登录页面和注销按钮。我们结合 Spring Security 实现需要用户名和密码登录的安全认证

创建sunny-eureka-service

这是eureka-server端,注册中心。

pom文件

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1.RELEASE</version>
</parent>

<dependencies>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

application.yml

改动点:
1.默认设置security登录账号密码
2.注册中心的地址,需要加上自己设置的账号密码

#服务端口号
server:
  port: 8888

spring:
  application:
    name: sunny-eureka-service
  security:
    user:
      name: admin
      password: 123456

eureka:
  instance:
    #为false时,那么注册到Eureka中的Ip地址就是本机的Ip地址
    prefer-ip-address: false
    #服务注册中心实例的主机名
    hostname: localhost
    health-check-url-path: /actuator/health
    status-page-url-path: /actuator/info
    metadata-map:
      user.name:  ${spring.security.user.name}
      user.password:  ${spring.security.user.password}
  client:
    # 表示是否从 eureka server 中获取注册信息(检索服务),默认是true
    fetch-registry: false
    # 表示是否将自己注册到 eureka server(向服务注册中心注册自己),默认是true
    register-with-eureka: false
    service-url:
      #服务注册中心的配置内容,指定服务注册中心的位置,eureka 服务器的地址(注意:地址最后面的 /eureka/ 这个是固定值)
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      #2、在原先的基础上添加security用户名和密码(例如:http://username:password@localhost:8000/eureka/)
      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@${eureka.instance.hostname}:${server.port}/eureka/

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS #显示详细信息

config类

新版本的spring-cloud2.0中: Spring Security默认开启了CSRF攻击防御
CSRF会将微服务的注册也给过滤了,虽然不会影响注册中心,但是其他客户端是注册不了的,这里配置i就是将csrf给关闭掉

@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and().httpBasic()
                .and()
                .csrf()
                .disable();
    }
}

启动类

@EnableEurekaServer
@SpringBootApplication
public class SpringBootApplicationEurekaServer {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplicationEurekaServer.class);
    }
}

创建sunny-admin-server-service

这是SpringBootAdmin Server端。

pom文件

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1.RELEASE</version>
</parent>

<dependencies>
    <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>
    <!--如果spring-boot-starter-web 排除掉tomcat,则可以引入jetty-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>

    <!-- admin server -->
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-server</artifactId>
        <version>2.2.1</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <!-- eureka客户端 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <!-- 健康监控 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
        <version>2.2.1.RELEASE</version>
    </dependency>

</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

application.yml

server:
  port: 8889

spring:
  application:
    name: sunny-admin-server-service
  security:
    user:
      name: admin
      password: 123456

eureka:
  instance:
    #服务注册中心实例的主机名
    hostname: localhost
    health-check-url-path: /actuator/health
    status-page-url-path: /actuator/info
    metadata-map:
      user.name:  ${spring.security.user.name}
      user.password:  ${spring.security.user.password}
  client:
    serviceUrl:
      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@${eureka.instance.hostname}:8888/eureka/

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS #显示详细信息

config类

@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 {
        // @formatter:off
        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();
        // @formatter:on
    }
}

启动类

@EnableAdminServer
@EnableDiscoveryClient
@SpringBootApplication
public class SpringBootApplicationMainAdminServer {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplicationMainAdminServer.class);
    }
}

创建sunny-admin-client-service

这是SpringBootAdmin Server端。

pom文件

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </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>
    </dependency>
</dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

application.yml

server:
  port: 8183

spring:
  application:
    name: sunny-admin-client-service
  security:
    user:
      name: admin
      password: 123456

eureka:
  instance:
    #服务注册中心实例的主机名
    hostname: localhost
    health-check-url-path: /actuator/health
    status-page-url-path: /actuator/info
    metadata-map:
      user.name:  ${spring.security.user.name}
      user.password:  ${spring.security.user.password}
  client:
    serviceUrl:
      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@${eureka.instance.hostname}:8888/eureka/

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS #显示详细信息

启动类

@EnableDiscoveryClient
@SpringBootApplication
public class SpringBootApplicationMainAdminClient {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplicationMainAdminClient.class);
    }
}

SpringBootAdmin集成邮箱服务

邮件通知

在 Spring Boot Admin 中 当注册的应用程序状态更改为DOWN、UNKNOWN、OFFLINE 都可以指定触发通知,下面讲解配置邮件通知。

在sunny-admin-server-service工程的pom文件中,加上email的依赖,如下

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

在配置文件application.yml文件中,配置收发邮件的配置:

spring:
  application:
    name: sunny-admin-server-service
  boot:
    admin:
      ui:
        title: sunny-admin-server-service
      notify:
        mail:
          from: xxxx@163.com #发件人
          to: xxxx@163.com,xxxx@163.com  #逗号分隔的收件人列表
          cc: xxxx@163.com,xxxx@163.com #逗号分隔的抄送收件人列表
          enabled: true # 开启邮箱通知
  mail:
    host: smtp.163.com 
    username: xxxx@163.com #自己的邮箱
    password: xxx #授权码
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true
    default-encoding: utf-8

配置后,重启sunny-admin-server-service工程,之后若出现注册的客户端的状态从 UP 变为 OFFLINE 或其他状态,服务端就会自动将电子邮件发送到上面配置的收件地址。

注意 : 配置了邮件通知后,会出现 反复通知 service offline / up。这个问题的原因在于 查询应用程序的状态和信息超时,下面给出两种解决方案:

#方法一:增加超时时间(单位:ms)

spring.boot.admin.monitor.read-timeout=20000

#方法二:关闭闭未使用或不重要的检查点

management.health.db.enabled=false
management.health.mail.enabled=false
management.health.redis.enabled=false
management.health.mongo.enabled=false

自定义通知

可以通过添加实现Notifier接口的Spring Beans来添加您自己的通知程序,最好通过扩展 AbstractEventNotifier或AbstractStatusChangeNotifier。在sunny-admin-server-service工程中编写一个自定义的通知器:

@Component
public class CustomNotifier  extends AbstractStatusChangeNotifier {
    private static final Logger LOGGER = LoggerFactory.getLogger( LoggingNotifier.class);

    public CustomNotifier(InstanceRepository repository) {
        super(repository);
    }

    @Override
    protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
        return Mono.fromRunnable(() -> {
            if (event instanceof InstanceStatusChangedEvent) {
                LOGGER.info("Instance {} ({}) is {}", instance.getRegistration().getName(), event.getInstance(),
                        ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus());

                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;
                }

            } else {
                LOGGER.info("Instance {} ({}) {}", instance.getRegistration().getName(), event.getInstance(),
                        event.getType());
            }
        });
    }
}

效果图,邮件通知

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=12tesopfl6i5t

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值