1. 程式人生 > >一起來學SpringBoot | 第十四篇:強大的 actuator 服務監控與管理

一起來學SpringBoot | 第十四篇:強大的 actuator 服務監控與管理

SpringBoot 是為了簡化 Spring 應用的建立、執行、除錯、部署等一系列問題而誕生的產物,自動裝配的特性讓我們可以更好的關注業務本身而不是外部的XML配置,我們只需遵循規範,引入相關的依賴就可以輕易的搭建出一個 WEB 工程

actuatorspring boot專案中非常強大一個功能,有助於對應用程式進行監視和管理,通過 restful api 請求來監管、審計、收集應用的執行情況,針對微服務而言它是必不可少的一個環節…

Endpoints

actuator 的核心部分,它用來監視應用程式及互動,spring-boot-actuator中已經內建了非常多的 Endpoints(health、info、beans、httptrace、shutdown等等)

,同時也允許我們自己擴充套件自己的端點

Spring Boot 2.0 中的端點和之前的版本有較大不同,使用時需注意。另外端點的監控機制也有很大不同,啟用了不代表可以直接訪問,還需要將其暴露出來,傳統的management.security管理已被標記為不推薦。

皮一下很開心

內建Endpoints

id desc Sensitive
auditevents 顯示當前應用程式的審計事件資訊 Yes
beans 顯示應用Spring Beans的完整列表 Yes
caches 顯示可用快取資訊 Yes
conditions
顯示自動裝配類的狀態及及應用資訊 Yes
configprops 顯示所有 @ConfigurationProperties 列表 Yes
env 顯示 ConfigurableEnvironment 中的屬性 Yes
flyway 顯示 Flyway 資料庫遷移資訊 Yes
health 顯示應用的健康資訊(未認證只顯示status,認證顯示全部資訊詳情) No
info 顯示任意的應用資訊(在資原始檔寫info.xxx即可) No
liquibase 展示Liquibase 資料庫遷移 Yes
metrics 展示當前應用的 metrics 資訊 Yes
mappings 顯示所有 @RequestMapping 路徑集列表 Yes
scheduledtasks 顯示應用程式中的計劃任務 Yes
sessions 允許從Spring會話支援的會話儲存中檢索和刪除使用者會話。 Yes
shutdown 允許應用以優雅的方式關閉(預設情況下不啟用) Yes
threaddump 執行一個執行緒dump Yes
httptrace 顯示HTTP跟蹤資訊(預設顯示最後100個HTTP請求 - 響應交換) Yes

匯入依賴

pom.xml 中新增 spring-boot-starter-actuator 的依賴

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

注意事項

如果要訪問info介面想獲取maven中的屬性內容請記得新增如下內容

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>build-info</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

屬性配置

application.properties 檔案中配置actuator的相關配置,其中info開頭的屬性,就是訪問info端點中顯示的相關內容,值得注意的是Spring Boot2.x中,預設只開放了info、health兩個端點,剩餘的需要自己通過配置management.endpoints.web.exposure.include屬性來載入(有include自然就有exclude,不做詳細概述了)。如果想單獨操作某個端點可以使用management.endpoint.端點.enabled屬性進行啟用或禁用

# 描述資訊
info.blog-url=http://blog.battcn.com
info.author=Levin
info.version[email protected].version@

# 載入所有的端點/預設只加載了 info / health
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

# 可以關閉制定的端點
management.endpoint.shutdown.enabled=false

# 路徑對映,將 health 路徑對映成 rest_health 那麼在訪問 health 路徑將為404,因為原路徑已經變成 rest_health 了,一般情況下不建議使用
# management.endpoints.web.path-mapping.health=rest_health

簡單測試

{
  "blog-url": "http://blog.battcn.com",
  "author": "Levin",
  "version": "0.0.1-SNAPSHOT"
}

自定義 - 重點

上面講了很多都是配置相關,以及自帶的一些端點,在實際應用中有時候預設並不能滿足我們的要求,比如Spring Boot預設的健康端點就很有可能不能滿足

預設裝配 HealthIndicators

下列是依賴spring-boot-xxx-starter後相關HealthIndicator的實現(通過management.health.defaults.enabled 屬性可以禁用它們),但想要獲取一些額外的資訊時,自定義的作用就體現出來了…

名稱 描述
CassandraHealthIndicator 檢查 Cassandra 資料庫是否啟動。
DiskSpaceHealthIndicator 檢查磁碟空間不足。
DataSourceHealthIndicator 檢查是否可以獲得連線 DataSource
ElasticsearchHealthIndicator 檢查 Elasticsearch 叢集是否啟動。
InfluxDbHealthIndicator 檢查 InfluxDB 伺服器是否啟動。
JmsHealthIndicator 檢查 JMS 代理是否啟動。
MailHealthIndicator 檢查郵件伺服器是否啟動。
MongoHealthIndicator 檢查 Mongo 資料庫是否啟動。
Neo4jHealthIndicator 檢查 Neo4j 伺服器是否啟動。
RabbitHealthIndicator 檢查 Rabbit 伺服器是否啟動。
RedisHealthIndicator 檢查 Redis 伺服器是否啟動。
SolrHealthIndicator 檢查 Solr 伺服器是否已啟動。

健康端點(第一種方式)

實現HealthIndicator介面,根據自己的需要判斷返回的狀態是UP還是DOWN,功能簡單。

package com.battcn.health;

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;

/**
 * <p>自定義健康端點</p>
 *
 * @author Levin
 * @since 2018/5/24 0024
 */
@Component("my1")
public class MyHealthIndicator implements HealthIndicator {

    private static final String VERSION = "v1.0.0";

    @Override
    public Health health() {
        int code = check();
        if (code != 0) {
            Health.down().withDetail("code", code).withDetail("version", VERSION).build();
        }
        return Health.up().withDetail("code", code)
                .withDetail("version", VERSION).up().build();
    }
    private int check() {
        return 0;
    }
}

簡單測試

{
  "status": "UP",
  "details": {
    "my1": {
      "status": "UP",
      "details": {
        "code": 0,
        "version": "v1.0.0"
      }
    },
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 100944310272,
        "free": 55071866880,
        "threshold": 10485760
      }
    }
  }
}

健康端點(第二種方式)

繼承AbstractHealthIndicator抽象類,重寫doHealthCheck方法,功能比第一種要強大一點點,預設的DataSourceHealthIndicator 、 RedisHealthIndicator 都是這種寫法,內容回撥中還做了異常的處理。

package com.battcn.health;

import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.stereotype.Component;

/**
 * <p>自定義健康端點</p>
 * <p>功能更加強大一點,DataSourceHealthIndicator / RedisHealthIndicator 都是這種寫法</p>
 *
 * @author Levin
 * @since 2018/5/24 0024
 */
@Component("my2")
public class MyAbstractHealthIndicator extends AbstractHealthIndicator {

    private static final String VERSION = "v1.0.0";

    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        int code = check();
        if (code != 0) {
            builder.down().withDetail("code", code).withDetail("version", VERSION).build();
        }
        builder.withDetail("code", code)
                .withDetail("version", VERSION).up().build();
    }

    private int check() {
        return 0;
    }
}

簡單測試

{
  "status": "UP",
  "details": {
    "my2": {
      "status": "UP",
      "details": {
        "code": 0,
        "version": "v1.0.0"
      }
    },
    "my1": {...},
    "diskSpace": {...}
  }
}

定義自己的端點

上面介紹的 infohealth 都是spring-boot-actuator內建的,真正要實現自己的端點還得通過@Endpoint、 @ReadOperation、@WriteOperation、@DeleteOperation

註解介紹

不同請求的操作,呼叫時缺少必需引數,或者使用無法轉換為所需型別的引數,則不會呼叫操作方法,響應狀態將為400(錯誤請求)

  • @Endpoint 構建 rest api 的唯一路徑
  • @ReadOperation GET請求,響應狀態為 200 如果沒有返回值響應 404(資源未找到)
  • @WriteOperation POST請求,響應狀態為 200 如果沒有返回值響應 204(無響應內容)
  • @DeleteOperation DELETE請求,響應狀態為 200 如果沒有返回值響應 204(無響應內容)
package com.battcn.endpoint;

import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>@Endpoint 是構建 rest 的唯一路徑 </p>
 * 不同請求的操作,呼叫時缺少必需引數,或者使用無法轉換為所需型別的引數,則不會呼叫操作方法,響應狀態將為400(錯誤請求)
 * <P>@ReadOperation = GET 響應狀態為 200 如果沒有返回值響應 404(資源未找到) </P>
 * <P>@WriteOperation = POST 響應狀態為 200 如果沒有返回值響應 204(無響應內容) </P>
 * <P>@DeleteOperation = DELETE 響應狀態為 200 如果沒有返回值響應 204(無響應內容) </P>
 *
 * @author Levin
 * @since 2018/5/24 0024
 */
@Endpoint(id = "battcn")
public class MyEndPoint {

    @ReadOperation
    public Map<String, String> hello() {
        Map<String, String> result = new HashMap<>();
        result.put("author", "Levin");
        result.put("age", "24");
        result.put("email", "[email protected]");
        return result;
    }
}

以為這就大功告成了嗎,現實告訴我的是spring-boot預設是不認識這玩意的,得申明成一個Bean(請看 主函式

皮一下很開心

主函式

package com.battcn;

import com.battcn.endpoint.MyEndPoint;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * @author Levin
 */
@SpringBootApplication
public class Chapter13Application {

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

    @Configuration
    static class MyEndpointConfiguration {
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnEnabledEndpoint
        public MyEndPoint myEndPoint() {
            return new MyEndPoint();
        }
    }
}

測試

{
  "author": "Levin",
  "age": "24",
  "email": "[email protected]"
}

總結

目前很多大佬都寫過關於 SpringBoot 的教程了,如有雷同,請多多包涵,本教程基於最新的 spring-boot-starter-parent:2.0.2.RELEASE編寫,包括新版本的特性都會一起介紹…

說點什麼

  • 個人QQ:1837307557
  • battcn開源群(適合新手):391619659
  • 微信公眾號(歡迎調戲):battcn

公眾號