服務監控之 Spring Boot Admin.


一、概述

 開始閱讀這篇文章之前,建議先閱讀下《SpringBoot 之Actuator》,該篇文章提到 Spring Boot Actuator 提供了對單個Spring Boot的監控,信息包含:應用狀態、內存、線程、堆棧等等,比較全面的監控了Spring Boot應用的整個生命周期。但是美中不足的是:

  1. 所有的監控都需要調用固定的接口來查看,如果全面查看應用狀態需要調用很多接口,並且接口返回的 Json 信息不方便運營人員理解;
  2. 如果Spring Boot 應用集群非常大,每個應用都需要調用不同的接口來查看監控信息,操作非常繁瑣低效。

 在這樣的背景下,就誕生了另外一個開源軟件:Spring Boot Admin。那么什么是 Spring Boot Admin 呢?Spring Boot Admin 是一個針對 Spring Boot Actuator 進行UI美化封裝的監控工具。集群的每個應用都認為是一個客戶端(或者說實例),通過HTTP或者使用 Eureka 注冊到 Spring Boot Admin Server中進行展示,Spring Boot Admin UI 使用AngularJs將數據展示在前端。

 下面將給大家介紹如何使用Spring Boot Admin對Spring Boot應用進行監控。

二、spring-boot-admin-starter-server

下面介紹 spring-boot-admin-server 的構建,要監控的每個客戶端(或者說實例),都可以把 Actuator 數據注冊到 server 中進行 UI 渲染展示。

1. pom.xml

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

2. application.yml

server:
  port: 3333

spring:
  application:
    name: monitor

3. Application.java

@SpringBootApplication
@EnableAdminServer
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}

做完以上動作,我們一個 spring-boot-admin-server 項目就搭建好了。以下是一些附加的功能:權限認證和郵件預警。

4. 配置 spring-security 權限驗證

  • pom.xml
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-server-ui-login</artifactId>
            <version>1.5.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
  • application.yml
security:
  user:
    name: ${monitor.user}
    password: ${monitor.password}
  • SecurityConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // Page with login form is served as /login.html and does a POST on /login
        http.formLogin().loginPage("/login.html").loginProcessingUrl("/login").permitAll();
        // The UI does a POST on /logout on logout
        http.logout().logoutUrl("/logout");
        // The ui currently doesn't support csrf
        http.csrf().disable();

        // Requests for the login page and the static assets are allowed
        //允許登錄頁面和靜態資源的請求
        http.authorizeRequests().antMatchers("/login.html", "/**/*.css", "/img/**", "/third-party/**")
                .permitAll();
        // ... and any other request needs to be authorized
        //這點重要:所有請求都需要認證
        http.authorizeRequests().antMatchers("/**").authenticated();

        // Enable so that the clients can authenticate via HTTP basic for registering
        http.httpBasic();
    }
}
  • 效果

5、郵件預警

  • pom.xml
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
            <version>1.5.12.RELEASE</version>
        </dependency>
  • application.yml
spring:
  mail:
    host: smtp.exmail.qq.com
    port: 465
    username: xxx
    password: xxx
    properties:
      mail:
        smtp:
          auth: true
          debug: true
          timeout: 0
          socketFactory:
            port: 465
            class: javax.net.ssl.SSLSocketFactory
  • NotifierConfig.java
/**
 * 重新配置消息通知
 *
 * @author : cuixiuyin
 */
@Configuration
@EnableScheduling
public class NotifierConfig {
    private static final Logger log = LoggerFactory.getLogger(NotifierConfig.class);

    @Autowired
    private JavaMailSender javaMailSender;

    @Autowired
    private RemindingNotifier remindingNotifier;

    @Bean
    @Primary
    public RemindingNotifier remindingNotifier() {

        RemindingNotifier remindingNotifier = new RemindingNotifier(new AbstractEventNotifier() {

            @Override
            protected void doNotify(ClientApplicationEvent event) throws Exception {
                if (event instanceof ClientApplicationStatusChangedEvent) {
                    ClientApplicationStatusChangedEvent changedEvent = (ClientApplicationStatusChangedEvent) event;
                    log.info("Application {} ({}) is {}", event.getApplication().getName(), event.getApplication().getId(), changedEvent.getTo().getStatus());
                    String text = String.format("應用:%s 服務ID:%s,服務ip:%s 狀態改變為:[%s ---> %s],時間:%s"
                            , event.getApplication().getName()
                            , event.getApplication().getId()
                            , event.getApplication().getHealthUrl()
                            , changedEvent.getFrom().getStatus()
                            , changedEvent.getTo().getStatus()
                            , new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(changedEvent.getTimestamp())));
                    log.warn(text);
                    SimpleMailMessage message = new SimpleMailMessage();
                    message.setFrom("xxx@qq.com");
                    message.setTo("xxx@163.com");
                    message.setSubject(event.getApplication().getName() + "服務狀態改變");
                    message.setText(text);
                    javaMailSender.send(message);
                } else {
                    log.info("Application {} ({}) {}", event.getApplication().getName(), event.getApplication().getId(), event.getType());
                }
            }
        });
        // 每5分鍾就需要提醒一次,並不一定會提醒,有 RemindingNotifier 里面的狀態進行決定
        remindingNotifier.setReminderPeriod(TimeUnit.MINUTES.toMillis(5));
        return remindingNotifier;
    }

    /**
     * 每隔一分鍾檢查還有那些需要進行提醒
     */
    @Scheduled(fixedRate = 1_000L)
    public void remind() {
        remindingNotifier.sendReminders();
    }
}
  • 效果

三、spring-boot-admin-starter-client

我們已經有了一個 spring-boot-admin-server,現在要做的就是如何把客戶端(或者說實例)的 Actuator 數據注冊到 Server 中。

1. pom.xml

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

2. application.yml

spring:
  application:
    name: dubbo-provider
  boot:
    admin:
      enabled: true
      client:
        instance:
          name: ${spring.application.name}
          prefer-ip: true
        url: http://127.0.0.1:3333
management:
  endpoints:
    web:
      exposure:
        include: '*'

如此,我們就把客戶端(或者說實例)的 Actuator 數據注冊到 Server 中了。

附錄

1. 效果圖


2.源代碼地址

Github 演示代碼地址:https://github.com/JMCuixy/dubbo-demo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM