1. 程式人生 > >Spring Boot Admin使用及心跳檢測原理

Spring Boot Admin使用及心跳檢測原理

轉自:http://blog.csdn.net/jrn1012/article/details/76906480

介紹

Spring Boot Admin是一個Github上的一個開源專案,它在Spring Boot Actuator的基礎上提供簡潔的視覺化WEB UI,是用來管理 Spring Boot 應用程式的一個簡單的介面,提供如下功能:

  • 顯示 name/id 和版本號
  • 顯示線上狀態
  • Logging日誌級別管理
  • JMX beans管理
  • Threads會話和執行緒管理
  • Trace應用請求跟蹤
  • 應用執行引數資訊,如: 
    • Java 系統屬性
    • Java 環境變數屬性
    • 記憶體資訊
    • Spring 環境屬性

Spring Boot Admin 包含服務端和客戶端,按照以下配置可讓Spring Boot Admin執行起來。

使用

Server端

1、pom檔案引入相關的jar包 
新建一個admin-server的Spring Boot專案,在pom檔案中引入server相關的jar包

   <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-server</artifactId>
            <version>1.5.3</version>
        </dependency
>
<dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-server-ui</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>de.codecentric</groupId
>
<artifactId>spring-boot-admin-starter-client</artifactId> <version>1.5.3</version> </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

其中spring-boot-admin-starter-client的引入是讓server本身能夠發現自己(自己也是客戶端)。

2、 application.yml配置

在application.yml配置如下,除了server.port=8083的配置是server 對外公佈的服務埠外,其他配置是server本身作為客戶端的配置,包括指明指向服務端的地址和當前應用的基本資訊,使用@@可以讀取pom.xml的相關配置。

在下面Client配置的講解中,可以看到下面類似的配置。

server:
  port: 8083
spring:
  boot:
    admin:
      url: http://localhost:8083
info:
  name: server
  description: @project[email protected]
  version: @project.version@
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

3、配置日誌級別

在application.yml的同級目錄,新增檔案logback.xml,用以配置日誌的級別,包含的內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <logger name="org.springframework.web" level="DEBUG"/>
    <jmxConfigurator/>
</configuration>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在此處配置成了DEBUG,這樣可以通過控制檯日誌檢視server端和client端的互動情況。

4、新增入口方法註解

在入口方法上新增@EnableAdminServer註解。

@Configuration
@EnableAutoConfiguration
@EnableAdminServer
public class ServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServerApplication.class, args);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

5、啟動專案

啟動admin-server專案後,可以看到當前註冊的客戶端,點選明細,還可以檢視其他明細資訊。

Spring Boot Admin Server

Client端

在上述的Server端配置中,server本身也作為一個客戶端註冊到自己,所以client配置同server端配置起來,比較見到如下。

建立一個admin-client專案,在pom.xml新增相關client依賴包。

1、pom.xml新增client依賴

    <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
            <version>1.5.3</version>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

2、application.yml配置

在application.yml配置註冊中心地址等資訊:

spring:
  boot:
    admin:
      url: http://localhost:8083
info:
  name: client
  description: @project[email protected]
  version: @project.version@
endpoints:
  trace:
    enabled: true
    sensitive: false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

3、配置日誌檔案

在application.yml的同級目錄,新增檔案logback.xml,用以配置日誌的級別,包含的內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <logger name="org.springframework.web" level="DEBUG"/>
    <jmxConfigurator/>
</configuration>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

配置為DEBUG的級別,可以輸出和伺服器的通訊資訊,以便我們在後續心跳檢測,瞭解Spring Boot Admin的實現方式。

4、啟動Admin-Client應用

啟動客戶端專案,在服務端監聽了客戶端的啟動,並在頁面給出了訊息提示,啟動後,服務端的介面顯示如下:(兩個客戶端都為UP狀態)

Spring Boot Admin Client 啟動後

以上就可以使用Spring Boot Admin的各種監控服務了,下面談一談客戶端和服務端怎麼樣做心跳檢測的。

心跳檢測/健康檢測原理

原理

在Spring Boot Admin中,Server端作為註冊中心,它要監控所有的客戶端當前的狀態。要知道當前客戶端是否宕機,剛釋出的客戶端也能夠主動註冊到服務端。

服務端和客戶端之間通過特定的介面通訊(/health介面)通訊,來監聽客戶端的狀態。因為客戶端和服務端不能保證釋出順序。

有如下的場景需要考慮:

  1. 客戶端先啟動,服務端後啟動
  2. 服務端先啟動,客戶端後啟動
  3. 服務端執行中,客戶端下線
  4. 客戶端執行中,服務端下線

所以為了解決以上問題,需要客戶端和服務端都設定一個任務監聽器,定時監聽對方的心跳,並在伺服器及時更新客戶端狀態。

上文的配置使用了客戶端主動註冊的方法。

除錯準備

為了理解Spring Boot Admin的實現方式,可通過DEBUG 和檢視日誌的方式理解伺服器和客戶端的通訊(心跳檢測)

  • 在pom.xml右鍵spring-boot-admin-server和spring-boot-admin-starter-client,Maven-> 
    DownLoad Sources and Documentation

  • 在logback.xml中設定日誌級別為DEBUG

客戶端發起POST請求

客戶端相關類

  • RegistrationApplicationListener
  • ApplicationRegistrator

在客戶端啟動的時候呼叫RegistrationApplicationListener的startRegisterTask,該方法每隔 registerPeriod = 10_000L,(10秒:預設)向服務端POST一次請求,告訴伺服器自身當前是有心跳的。

  • RegistrationApplicationListener
    @EventListener
    @Order(Ordered.LOWEST_PRECEDENCE)
    public void onApplicationReady(ApplicationReadyEvent event) {
        if (event.getApplicationContext() instanceof WebApplicationContext && autoRegister) {
            startRegisterTask();
        }
    }

    public void startRegisterTask() {
        if (scheduledTask != null && !scheduledTask.isDone()) {
            return;
        }

        scheduledTask = taskScheduler.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                registrator.register();
            }
        }, registerPeriod);
        LOGGER.debug("Scheduled registration task for every {}ms", registerPeriod);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • ApplicationRegistrator
 public boolean register() {
        boolean isRegistrationSuccessful = false;
        Application self = createApplication();
        for (String adminUrl : admin.getAdminUrl()) {
            try {
                @SuppressWarnings("rawtypes") ResponseEntity<Map> response = template.postForEntity(adminUrl,
                        new HttpEntity<>(self, HTTP_HEADERS), Map.class);

                if (response.getStatusCode().equals(HttpStatus.CREATED)) {
                    if (registeredId.compareAndSet(null, response.getBody().get("id").toString())) {
                        LOGGER.info("Application registered itself as {}", response.getBody());
                    } else {
                        LOGGER.debug("Application refreshed itself as {}", response.getBody());
                    }

                    isRegistrationSuccessful = true;
                    if (admin.isRegisterOnce()) {
                        break;
                    }
                } else {
                    if (unsuccessfulAttempts.get() == 0) {
                        LOGGER.warn(
                                "Application failed to registered itself as {}. Response: {}. Further attempts are logged on DEBUG level",
                                self, response.toString());
                    } else {
                        LOGGER.debug("Application failed to registered itself as {}. Response: {}", self,
                                response.toString());
                    }
                }
            } catch (Exception ex) {
                if (unsuccessfulAttempts.get() == 0) {
                    LOGGER.warn(
                            "Failed to register application as {} at spring-boot-admin ({}): {}. Further attempts are logged on DEBUG level",
                            self, admin.getAdminUrl(), ex.getMessage());
                } else {
                    LOGGER.debug("Failed to register application as {} at spring-boot-admin ({}): {}", self,
                            admin.getAdminUrl(), ex.getMessage());
                }
            }
        }
        if (!isRegistrationSuccessful) {
            unsuccessfulAttempts.incrementAndGet();
        } else {
            unsuccessfulAttempts.set(0);
        }
        return isRegistrationSuccessful;
    }
  • 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
  • 46
  • 47

在主要的register()方法中,向服務端POST了Restful請求,請求的地址為/api/applications 
並把自身資訊帶了過去,服務端接受請求後,通過sha-1演算法計算客戶單的唯一ID,查詢hazelcast快取資料庫,如第一次則寫入,否則更新。

服務端接收處理請求相關類

  • RegistryController
    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<Application> register(@RequestBody Application application) {
        Application applicationWithSource = Application.copyOf(application).withSource("http-api")
                .build();
        LOGGER.debug("Register application {}", applicationWithSource.toString());
        Application registeredApp = registry.register(applicationWithSource);
        return ResponseEntity.status(HttpStatus.CREATED).body(registeredApp);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • ApplicationRegistry
public Application register(Application application) {
        Assert.notNull(application, "Application must not be null");
        Assert.hasText(application.getName(), "Name must not be null");
        Assert.hasText(application.getHealthUrl(), "Health-URL must not be null");
        Assert.isTrue(checkUrl(application.getHealthUrl()), "Health-URL is not valid");
        Assert.isTrue(
                StringUtils.isEmpty(application.getManagementUrl())
                        || checkUrl(application.getManagementUrl()), "URL is not valid");
        Assert.isTrue(
                StringUtils.isEmpty(application.getServiceUrl())
                        || checkUrl(application.getServiceUrl()), "URL is not valid");

        String applicationId = generator.generateId(application);
        Assert.notNull(applicationId, "ID must not be null");

        Application.Builder builder = Application.copyOf(application).withId(applicationId);
        Application existing = getApplication(applicationId);
        if (existing != null) {
            // Copy Status and Info from existing registration.
            builder.withStatusInfo(existing.getStatusInfo()).withInfo(existing.getInfo());
        }
        Application registering = builder.build();

        Application replaced = store.save(registering);
        if (replaced == null) {
            LOGGER.info("New Application {} registered ", registering);
            publisher.publishEvent(new ClientApplicationRegisteredEvent(registering));
        } else {
            if (registering.getId().equals(replaced.getId())) {
                LOGGER.debug("Application {} refreshed", registering);
            } else {
                LOGGER.warn("Application {} replaced by Application {}", registering, replaced);
            }
        }
        return registering;
    }
  • 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
  • HazelcastApplicationStore (快取資料庫)

在上述更新狀態使用了publisher.publishEvent事件訂閱的方式,接受者接收到該事件,做應用的業務處理,在這塊使用這種方式個人理解是為了程式碼的複用性,因為服務端定時輪詢客戶端也要更新客戶端在伺服器的狀態。

pulishEvent設計到的類有:

  • StatusUpdateApplicationListener->onClientApplicationRegistered
  • StatusUpdater–>updateStatus

這裡不詳細展開,下文還會提到,通過日誌,可以檢視到客戶端定時傳送的POST請求:

客戶端定時POST

服務端定時輪詢

在伺服器宕機的時候,伺服器接收不到請求,此時伺服器不知道客戶端是什麼狀態,(當然可以說伺服器在一定的時間裡沒有收到客戶端的資訊,就認為客戶端掛了,這也是一種處理方式),在Spring Boot Admin中,服務端通過定時輪詢客戶端的/health介面來對客戶端進行心態檢測。

這裡設計到主要的類為:

  • StatusUpdateApplicationListene
@EventListener
    public void onApplicationReady(ApplicationReadyEvent event) {
        if (event.getApplicationContext() instanceof WebApplicationContext) {
            startStatusUpdate();
        }
    }
    public void startStatusUpdate() {
        if (scheduledTask != null && !scheduledTask.isDone()) {
            return;
        }

        scheduledTask = taskScheduler.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                statusUpdater.updateStatusForAllApplications();
            }
        }, updatePeriod);
        LOGGER.debug("Scheduled status-updater task for every {}ms", updatePeriod);

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • StatusUpdater
    public void updateStatusForAllApplications() {
        long now = System.currentTimeMillis();
        for (Application application : store.findAll()) {
            if (now - statusLifetime > application.getStatusInfo().getTimestamp()) {
                updateStatus(application);
            }
        }
    }
public void updateStatus(Application application) {
        StatusInfo oldStatus = application.getStatusInfo();
        StatusInfo newStatus = queryStatus(application);
        boolean statusChanged = !newStatus.equals(oldStatus);

        Application.Builder builder = Application.copyOf(application).withStatusInfo(newStatus);

        if (statusChanged && !newStatus.isOffline() && !newStatus.isUnknown()) {
            builder.withInfo(queryInfo(application));
        }

        Application newState = builder.build();
        store.save(newState);

        if (statusChanged) {
            publisher.publishEvent(
                    new ClientApplicationStatusChangedEvent(newState, oldStatus, newStatus));
        }
    }
  • 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 Boot Admin使用心跳檢測原理

轉自:http://blog.csdn.net/jrn1012/article/details/76906480介紹Spring Boot Admin是一個Github上的一個開源專案,它在Spring Boot Actuator的基礎上提供簡潔的視覺化WEB UI,是用來管

spring-boot-admin原始碼分析單機監控spring-boot-monitor的實現(三)

SpringBootMonitor spring-boot-admin原始碼分析及單機監控spring-boot-monitor的實現(一) spring-boot-admin原始碼分析及單機監控spring-boot-monitor的實現(二)

spring-boot-admin原始碼分析單機監控spring-boot-monitor的實現(二)

SpringBootMonitor spring-boot-admin原始碼分析及單機監控spring-boot-monitor的實現(一) spring-boot-admin原始碼分析及單機監控spring-boot-monitor的實現(二)

spring-boot-admin原始碼分析單機監控spring-boot-monitor的實現(一)

SpringBootMonitor spring-boot-admin原始碼分析及單機監控spring-boot-monitor的實現(一) spring-boot-admin原始碼分析及單機監控spring-boot-monitor的實現(二) spring-boot-ad

Spring Boot Admin簡介實踐

## 問題 在若干年前的單體應用時代,我們可以相對輕鬆地對整個業務專案進行健康檢查、指標監控、配置管理等等專案治理。如今隨著微服務的發展,我們將大型單體應用按業務模型進行劃分,以此形成眾多小而自治的微服務,我們品嚐到了微服務的甜頭:異常隔離、獨立部署和釋出、服務伸縮、便於協作開發...我們的專案服務更加解耦合

007-Spring Boot @Enable*註解的工作原理

sync express override factor run ext soft navi itself 一、@Enable* 啟用某個特性的註解 1、EnableConfigurationProperties 回顧屬性裝配 application.properti

Spring Boot Admin 集成自定義監控告警

doctype etc exce err art bstr tst notifier ESS Spring Boot Admin 集成自定義監控告警 前言 Spring Boot Admin 是一個社區項目,可以用來監控和管理 Spring Boot 應用並且提供 UI,詳

spring boot admin 集成的簡單配置隨筆

舍得 int 方便 localhost github ble 是不是 截圖 代碼 和我並肩作戰的同事也要相繼離職了,心裏還是有很多不舍得,現在業務也陸陸續續落在了肩頭,上午項目經理讓我把spring boot admin集成到現在的項目中,已遍後續的監控。 哇!我哪裏搞過這

Spring Boot Admin 使用

Spring Boot Admin 使用 簡介 服務端整合(admin-server) 客戶端整合(admin-client) Spring Boot 2.x 監控中心 Admin 的簡單使用demo。 dem

spring boot 實踐學習案例---spring boot 初學者核心技術鞏固的最佳實踐

    chapter-1-spring-boot-quickstart Spring Boot 入門、Spring Boot 配置、Web 開發、模板引擎、資料儲存、資料快取 案例更新 7 months ago

spring boot admin 整合的簡單配置隨筆

和我並肩作戰的同事也要相繼離職了,心裡還是有很多不捨得,現在業務也陸陸續續落在了肩頭,上午專案經理讓我把spring boot admin整合到現在的專案中,已遍後續的監控。 哇!我哪裡搞過這個!心裡好慌,好在我面向物件雖然不是很精通,但是面向百度我倒是很拿手,於是開啟了,面向百度程式設計,現在已經成功過了

Spring Boot Admin 詳解(Spring Boot 2.0,基於 Eureka 的實現)

Spring Boot Admin 用於監控基於 Spring Boot 的應用,它是在 Spring Boot Actuator 的基礎上提供簡潔的視覺化 WEB UI。 (一)簡介 Spring Boot Admin 提供了很多功能,如顯示 name、id 和 version,顯示線上狀態,

Spring Boot面試殺手鐗————自動配置原理

引言 不論在工作中,亦或是求職面試,Spring Boot已經成為我們必知必會的技能項。除了某些老舊的政府專案或金融專案持有觀望態度外,如今的各行各業都在飛速的擁抱這個已經不是很新的Spring啟動框架。 當然,作為Spring Boot的精髓,自動配置原理的工作過程往往只有在“面試”的

Spring Boot Admin【Finchley 版】

一、 Spring Boot Admin介紹 二、 Spring Boot Admin監控Spring Boot應用 搭建Admin Server端 Admin Cl

SpringBoot | 第八章:搭建Spring Boot Admin分散式微服務監控中心

(一)、什麼是Spring Boot Admin       Spring Boot Admin 是一個針對spring-boot的actuator介面進行UI美化封裝的監控工具。他可以返回在列表中瀏覽所有被監控spring-boot專案的基本資訊比如

分散式、微服務架構Spring Boot入門例項介紹

spring boot入門 -- 介紹和第一個例子 “越來越多的企業選擇使用spring boot 開發系統,spring boot牛在什麼地方?難不難學?心動不如行動,讓我們一起開始學習吧!” 使用Spring boot ,可以輕鬆的建立獨立執行的程式,非常容易構建獨立的服務元件,是實現

springboot(二十):使用spring-boot-adminspring-boot服務進行監控

上一篇文章《springboot(十九):使用Spring Boot Actuator監控應用》介紹了Spring Boot Actuator的使用,Spring Boot Actuator提供了對單個Spring Boot的監控,資訊包含:應用狀態、記憶體、執行緒、堆疊

使用spring-boot-adminspring-boot服務進行監控

一 服務端 1.建立一個web專案 <parent> <groupId>org.springframework.boot</groupId> <

SpringBoot | 第二十八章:監控管理之Spring Boot Admin使用

前言 上一章節,我們介紹了Actuator的使用,知道了可通過訪問不同的端點路徑,獲取相應的監控資訊。但使用後也能發現,返回的監控資料都是以JSON串的形式進行返回的,對於實施或者其他人員來說,不是很直觀,而當需要監控的應用越來越多時,依次去訪問對應的應用也過於繁瑣和低效了。所以,本章節來介紹下Spring

Springboot: Springboot + spring boot admin 監控 spring security許可權控制

Springboot admin 很好的提供了對Springboot的監控,但是不建議直接將admin整合到已有的專案中。於是我另起一個專案,考慮到不能讓所有人都能看到這些資料了,於是引入了spring security。   本次使用的是spring-boot-admin-s