聊聊springboot專案如何實現自定義actuator端點

linyb極客之路發表於2021-09-25

前言

用過springboot的朋友,可能會知道springboot有四大神器:自動裝配、starter、cli、actuator。其中actuator可幫助你在將應用程式推送到生產環境時監控和管理應用程式。你可以選擇使用 HTTP 端點或 JMX 來管理和監控你的應用程式。 審計、健康和指標收集也可以自動應用於你的應用程式。

actuator預設為我們內建了以下端點

ID描述預設啟用預設公開
auditevents公開當前應用程式的審計事件資訊YesNo
beans顯示應用程式中所有Spring bean的完整列表YesNo
conditions顯示在配置和自動配置類上評估的條件以及它們是否匹配的原因YesNo
configprops顯示所有@ConfigurationProperties對照的列表YesNo
env從Spring的ConfigurableEnvironment中公開屬性YesNo
flyway顯示已應用的任何Flyway資料庫遷移YesNo
health顯示應用程式健康資訊YesYes
httptrace顯示HTTP跟蹤資訊(預設情況下,最後100個HTTP請求-響應互動)YesNo
info顯示任意應用程式資訊YesYes
loggers顯示和修改應用程式中記錄器的配置YesNo
liquibase顯示已應用的任何Liquibase資料庫遷移YesNo
metrics顯示當前應用程式的“指標”資訊YesNo
mappings顯示所有@RequestMapping路徑對照的列表YesNo
scheduledtasks顯示應用程式中排程的任務YesNo
sessions允許從Spring Session支援的會話儲存中檢索和刪除使用者會話YesNo
shutdown讓應用程式優雅地關閉NoNo
threaddump執行執行緒轉儲YesNo

如果你的應用程式是一個web應用程式(Spring MVC、Spring WebFlux或Jersey),你可以使用以下附加端點

ID描述預設啟用預設公開
heapdump返回一個GZip壓縮的hprof堆轉儲檔案YesNo
jolokia在HTTP上公開JMX bean(當Jolokia在類路徑上時,WebFlux不可用)YesNo
logfile返回日誌檔案的內容,支援使用HTTP Range header來檢索日誌檔案內容的一部分YesNo
prometheus公開指標,該格式可以被Prometheus伺服器採集YesNo

注: actuator 在springboot 1.X 和springboot 2.X 存在較大的差異,本文以springboot 2.X 作為本文的講解

通常情況下,actuator內建的端點就可以滿足我們的日常需求了,但有時候我們需要自定義端點。下面就列舉一下幾種常用的自定義端點

自定義端點

自定義前置條件,在pom.xml引入

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
1、自定義health

當內建的health端點資訊不滿足用來判斷我們專案是否健康時,我們可以自定義health

通過實現org.springframework.boot.actuate.health.HealthIndicator介面,形如

@Component
public class CustomHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        int errorCode = check();
        if (errorCode == 1) {
            return Health.down().withDetail("Error Code", errorCode).build();
        }
        return Health.up().build();
    }

    private int check() {
        // perform some specific health check
        return ThreadLocalRandom.current().nextInt(5);
    }

}

或者通過繼承org.springframework.boot.actuate.health.AbstractHealthIndicator,形如

@Component("otherCustom")
public class CustomAbstractHealthIndicator extends AbstractHealthIndicator {
    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {

        int errorCode = check();
        if (errorCode == 1) {
            builder.down().down().withDetail("Error Code", errorCode).build();
            return;
        }
        builder.up().build();

    }

    private int check() {
        // perform some specific health check
        return ThreadLocalRandom.current().nextInt(5);
    }
}

推薦使用繼承AbstractHealthIndicator 這種方式。在配置檔案中作如下配置,可以檢視詳細的健康資訊


management:
   endpoint:
      health:
        show-details: always

通過訪問http://ip:port/actuator/health進行檢視,形如下


從圖片我們可以看出,我們自定義的health端點資訊,如果@Component不指定name,形如CustomHealthIndicator ,預設是取custom作為自定義端點物件

2、自定義info

我們可以通過實現org.springframework.boot.actuate.info.InfoContributor介面,來暴露一些我們想展示的資訊。形如

@Component
public class CustomInfoContributor implements InfoContributor {

    @Override
    public void contribute(Info.Builder builder) {
        builder.withDetail("customInfo", Collections.singletonMap("hello", "world"));
    }

}

通過訪問http://ip:port/actuator/info進行檢視,形如下

3、自定義endpoint

有時候我們需要自定義自己的端點,我們可以通過
@Endpoint註解 + @ReadOperation、@WriteOperation、@DeleteOperation註解來實現自定義端點。形如下

@Component
@Endpoint(id = "customEndpoint")
public class CustomEndpoint {

  // @ReadOperation 對應GET請求

  /**
   * 請求示例:
   * GET http://localhost:8080/actuator/customEndpoint/zhangsan/20
   * @param username
   * @param age
   *
   * @return
   */
  @ReadOperation
  public Map<String, Object> endpointByGet(@Selector String username,@Selector Integer age) {
    Map<String, Object> customMap = new HashMap<>();
    customMap.put("httpMethod", HttpMethod.GET.toString());
    customMap.put("username",username);
    customMap.put("age",age);
    return customMap;
  }


  // @WriteOperation 對應POST請求

  /**
   * 請求示例:
   * POST http://localhost:8080/actuator/customEndpoint
   *
   * 請求引數為json格式
   *
   * {
   *     "username": "zhangsan",
   *     "age": 20
   * }
   *
   * @param username 引數都為必填項
   * @param age 引數都為必填項
   * @return
   */
  @WriteOperation
  public Map<String, Object> endpointByPost(String username,Integer age) {
    Map<String, Object> customMap = new HashMap<>();
    customMap.put("httpMethod", HttpMethod.POST.toString());
    customMap.put("username",username);
    customMap.put("age",age);
    return customMap;
  }


  // @DeleteOperation 對應Delete請求

  /**
   * 請求示例:
   * DELETE http://localhost:8080/actuator/customEndpoint
   *
   * @return
   */
  @DeleteOperation
  public Map<String, Object> endpointByDelete() {
    Map<String, Object> customMap = new HashMap<>();
    customMap.put("httpMethod", HttpMethod.DELETE.toString());

    return customMap;
  }

程式碼片段裡面有比較詳細的註釋,這邊就不在論述。這邊有個細節就是,我們需要在yml作如下配置來暴露我們自定義的端點

通過


management:
  endpoints:
    web:
      exposure:
        include: customEndpoint

或者


management:
  endpoints:
    web:
      exposure:
        include: "*"

總結

本文僅介紹幾種相對通用的自定義端點,更詳細的端點介紹可以檢視官網,連結如下

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator

demo連結

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-custom-actuator-endpoint

相關文章