本文集成 Spring Boot Admin 实现系统监控, 并通过 STMP 实现应用下线邮件通知。

前言

*最近在做一个项目,由多个 Spring Boot 单体应用组成。希望能对应用进行监控,同时在应用下线时发通知提醒。

Spring Boot Admin简介

使用Spring Boot Admin可以管理和监控你的 Spring Boot 项目。

它分为客户端服务端两部分,客户端添加到你的 Spring Boot 应用增加暴漏相关信息的HTTP接口,然后注册到Spring Boot Admin服务端,这一步骤可以直接向服务端注册,也可以通过Eureka或者Consul进行注册。

Spring Boot Admin Server通过Vue.js程序监控信息进行可视化呈现。支持多种事件通知操作。

Jar包版本信息

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.7.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <skipTests>true</skipTests>
    <spring-boot-admin.version>2.1.0</spring-boot-admin.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-dependencies</artifactId>
            <version>${spring-boot-admin.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

实现过程

搭建 Service 端

*因为篇幅原因,这里只展示重点内容。

引入依赖

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-server</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>

编写 application.yml 配置

spring:
  application:
	# 应用名称
    name: system
  security:
    user:
      # 登录账号
      name: user
      # 登录密码
      password: 123456
server:
  port: 9999

添加 @EnableAdminServer 注解

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

添加安全认证

因为是部署在公网中,所以增加权限账号登录验证。账号密码已经在 application.yml 中配置好了。还需要实现如下权限拦截。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 跨域设置,SpringBootAdmin客户端通过instances注册
        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .ignoringAntMatchers("/instances");

        // 静态资源
        http.authorizeRequests().antMatchers("/assets/**").permitAll();
        // 所有请求必须通过认证
        http.authorizeRequests().anyRequest().authenticated();

        // 整合spring-boot-admin-server-ui
        http.formLogin().loginPage("/login").permitAll();
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/login");

        // 启用basic认证
        http.httpBasic();
    }
}

至此,Service 端 已完成配置,对应的访问地址:http://localhost:9999

配置 Client 端

引入依赖

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>

编写 application.yml 配置

spring:
  application:
    name: wx-dev
  boot:
    admin:
      client:
        # Spring Boot Admin 服务端地址
        url: http://localhost:9999/
        username: user
        password: 123456
        instance:
          prefer-ip: true
management:
  endpoint:
    health:
      # 端点健康情况,默认值 "never",设置为 "always" 可以显示硬盘使用情况和线程情况
      show-details: always
  endpoints:
    web:
      exposure:
        # 设置端点暴露的哪些内容,默认 ["health","info"],设置 "*" 代表暴露所有可访问的端点
        include: "*"

至此,已经完成 client 配置。接下来配置邮箱通知。

配置邮箱通知

这里我用的是,网易邮箱实现邮箱通知。

引入依赖到server

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

编写server端的application.yml 配置

spring:
  mail:
    # 网易邮箱服务地址
    host: smtp.163.com
    # 网易邮箱账号
    username: xxx@163.com
    # 授权码
    password: 授权码
    default-encoding: UTF-8
  boot:
    admin:
      notify:
        mail:
          # 接收人列表(用逗号隔开)
          to: xxx@163.com,xxx@qq.com
          # 发送人信息
          from: 应用下线通知<xxx@163.com>
          # 启动通知
          enabled: true
          # 忽略应用上线状态
          ignore-changes: {"UNKNOWN:UP"}

至此,已完成应用下线时邮件通知。

可能遇到的问题

使用docker部署产生问题

应用部署在docker中,注册到server, 会默认获取镜像实例ID(例如sd1kj1g)作为访问路径(http://sd1kj1g:8080)。而server无法通过访问地址,获取该应用信息。导致应用一直处于下线状态,无法正常监控。(这又诱发了下面反复报错的问题)

解决方案:(仅限同一网络下),客户端中application.yml,将prefer-ip: true(即,将内网 IP替代镜像名)。

详见:下面两篇文章。

应用掉线导致的反复报错问题

默认tomcat部署时,应用掉线后,会反复重连,一直报错。

解决方案:改用jetty 部署(一款比tomcat更轻量级的应用容器)。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <groupId>org.springframework.boot</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

实现效果

image-20200927221316343

image-20200927221420126

image-20200927221316343

扩展阅读

  • Zabbix:老牌监控的优秀代表。
  • open-falcon:小米出品,国内流行。
  • Prometheus:号称下一代监控系统。

Zabbix

Zabbix 1998 年诞生,核心组件采用 C 语言开发,Web 端采用 PHP 开发。它属于老牌监控系统中的优秀代表,监控功能很全面,使用也很广泛,差不多有 70% 左右的互联网公司都曾使用过 Zabbix 作为监控解决方案。

image-20210401222919113

open-falcon

Open-falcon 是小米 2015 年开源的企业级监控工具,采用 GoPython 语言开发,这是一款灵活、高性能且易扩展的新一代监控方案,目前小米、美团、滴滴等超过 200 家公司在使用它。

image-20200930100334165

Prometheus

Prometheus(普罗米修斯):是由前 google 员工 2015 年正式发布的开源监控系统,采用 Go 语言开发。它不仅有一个很酷的名字,同时它有 Google 与 k8s 的强力支持,开源社区异常火爆。

image-20200930095719794

博客园-未读代码:使用 Spring Boot Admin 监控你的 Spring Boot 程序,支持异常邮件通知,写的很详细的一篇文章,建议可以看一下。