括展actuator health check

gongchengship發表於2024-10-17

方式一:

為了定製 Spring Boot 的 Actuator 來實現你所描述的功能,即在呼叫自己的 /actuator/health 時,服務端能夠自動呼叫 4 個下游 API 的 /actuator/health,並將其檢查結果與自己的健康狀態一起返回,可以按照以下步驟進行操作:

實現思路:

  1. 建立自定義的 HealthIndicator:Spring Boot 提供了 HealthIndicator 介面,允許你自定義健康檢查邏輯。我們可以透過實現該介面來定製對外部 API 的健康檢查。

  2. 整合多個 API 的健康狀態:在自定義的 HealthIndicator 實現中,我們可以發起 HTTP 請求呼叫 4 個下游 API 的健康檢查介面,獲取它們的健康狀態。

  3. 將各 API 的狀態與自身服務的健康狀態合併:透過 Health.Builder 將自身服務的健康狀態和 4 個下游 API 的健康檢查結果合併,返回給呼叫方。

詳細實現步驟:

1. 引入必要的依賴

確保你的 pom.xml 中包含以下依賴項,特別是用於發起 HTTP 請求的 spring-boot-starter-webspring-boot-starter-actuator

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

2. 建立自定義的 HealthIndicator

首先,需要實現 HealthIndicator 介面,用於檢查下游 API 的健康狀態。可以使用 Spring 的 RestTemplate 來發起 HTTP 請求。

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

@Component
public class DownstreamApiHealthIndicator implements HealthIndicator {

    private final RestTemplate restTemplate;

    public DownstreamApiHealthIndicator(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public Health health() {
        // 假設下游 API 的健康檢查地址
        String[] urls = {
            "http://api1/actuator/health",
            "http://api2/actuator/health",
            "http://api3/actuator/health",
            "http://api4/actuator/health"
        };

        // 構建健康狀態
        Health.Builder builder = Health.up();

        for (String url : urls) {
            try {
                // 發起 GET 請求獲取健康狀態
                Health response = restTemplate.getForObject(url, Health.class);
                if (response != null && response.getStatus().equals(Health.up().getStatus())) {
                    builder.withDetail(url, "UP");
                } else {
                    builder.withDetail(url, "DOWN");
                }
            } catch (Exception e) {
                // 如果請求失敗,認為該服務不可達
                builder.withDetail(url, "DOWN").down();
            }
        }

        return builder.build();
    }
}

在這裡,我們實現了 DownstreamApiHealthIndicator,用於對 4 個下游 API 進行健康檢查,並將結果整合到健康狀態中。

3. 建立 RestTemplate Bean

為了發起 HTTP 請求,需要建立一個 RestTemplate Bean。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

4. 將自定義 HealthIndicator 與 Spring Boot 的 /actuator/health 結合

Spring Boot 會自動發現實現了 HealthIndicator 介面的 Bean,並將其整合到 /actuator/health 的響應中。因此,你只需要將自定義的 DownstreamApiHealthIndicator 實現放入 Spring 的上下文中即可。

5. 調整返回健康資訊的格式(可選)

如果你想控制健康資訊的返回格式,可以透過修改 application.properties 中的配置來實現。比如,可以透過下面的配置展示詳細的健康狀態資訊:

management.endpoint.health.show-details=always
management.endpoint.health.show-components=always

6. 執行結果

當你訪問 /actuator/health 時,將會得到如下類似的響應,包含自身服務的健康狀態以及 4 個下游 API 的健康狀態:

{
    "status": "UP",
    "details": {
        "http://api1/actuator/health": "UP",
        "http://api2/actuator/health": "UP",
        "http://api3/actuator/health": "DOWN",
        "http://api4/actuator/health": "UP"
    }
}

這裡,status 表示你的服務的整體健康狀態,details 部分包含了各下游 API 的健康檢查結果。

7. 其他可選配置

如果下游 API 的健康檢查比較耗時,或者你想避免同步呼叫帶來的阻塞,可以考慮使用非同步呼叫來併發檢查下游服務的狀態。你可以使用 CompletableFuture 或者其他非同步處理方式來併發發起 HTTP 請求,從而減少整體健康檢查的響應時間。

使用 CompletableFuture 實現非同步健康檢查

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

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@Component
public class DownstreamApiHealthIndicator implements HealthIndicator {

    private final RestTemplate restTemplate;

    public DownstreamApiHealthIndicator(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public Health health() {
        String[] urls = {
            "http://api1/actuator/health",
            "http://api2/actuator/health",
            "http://api3/actuator/health",
            "http://api4/actuator/health"
        };

        Health.Builder builder = Health.up();

        // 非同步檢查下游 API 的健康狀態
        CompletableFuture[] futures = new CompletableFuture[urls.length];
        for (int i = 0; i < urls.length; i++) {
            String url = urls[i];
            futures[i] = CompletableFuture.runAsync(() -> {
                try {
                    Health response = restTemplate.getForObject(url, Health.class);
                    if (response != null && response.getStatus().equals(Health.up().getStatus())) {
                        builder.withDetail(url, "UP");
                    } else {
                        builder.withDetail(url, "DOWN");
                    }
                } catch (Exception e) {
                    builder.withDetail(url, "DOWN").down();
                }
            });
        }

        // 等待所有任務完成
        CompletableFuture.allOf(futures).join();

        return builder.build();
    }
}

透過這種方式,你可以大大減少等待時間,從而提高整體的響應效率。

總結

  1. 透過實現自定義的 HealthIndicator,你可以將下游 API 的健康檢查整合到自身服務的健康檢查中。
  2. 可以使用 RestTemplate 發起同步或非同步的 HTTP 請求,獲取下游 API 的健康狀態。
  3. 利用 Spring Boot 的自動發現機制,你的自定義 HealthIndicator 會被自動整合到 /actuator/health 的輸出中。

方式二:

在 Spring Boot 中,你可以使用 組合多個 HealthIndicator 來執行多個健康檢查,並將它們的結果組合起來。Spring Boot 提供了一種方式來組合多個健康檢查,叫做 CompositeHealthContributor。你可以透過實現多個 HealthIndicator 並將它們組合到一個 CompositeHealthContributor 中。

這裡是詳細步驟和示例程式碼來展示如何組合多個健康檢查:

實現步驟

  1. 實現多個 HealthIndicator:首先,你需要為每個要檢查的下游 API 或其他資源實現各自的 HealthIndicator

  2. 組合多個 HealthIndicator:透過實現 CompositeHealthContributor,你可以將多個 HealthIndicator 組合到一起。

  3. 整合到 Spring Boot Actuator:Spring Boot 會自動發現 HealthIndicatorCompositeHealthContributor,並將它們整合到 /actuator/health

示例程式碼

1. 實現多個 HealthIndicator

這裡我們建立兩個簡單的健康檢查類,分別檢查兩個下游 API 的健康狀態。

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

@Component
public class DownstreamApi1HealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        // 這裡是對第一個下游 API 的健康檢查邏輯
        // 假設呼叫 API 成功就返回 UP,否則返回 DOWN
        boolean api1IsUp = checkApi1Health();
        if (api1IsUp) {
            return Health.up().withDetail("API 1", "Available").build();
        } else {
            return Health.down().withDetail("API 1", "Unavailable").build();
        }
    }

    private boolean checkApi1Health() {
        // 模擬健康檢查的邏輯,可以是實際的 HTTP 請求
        return true; // 假設 API 1 是可用的
    }
}

@Component
public class DownstreamApi2HealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        // 這裡是對第二個下游 API 的健康檢查邏輯
        boolean api2IsUp = checkApi2Health();
        if (api2IsUp) {
            return Health.up().withDetail("API 2", "Available").build();
        } else {
            return Health.down().withDetail("API 2", "Unavailable").build();
        }
    }

    private boolean checkApi2Health() {
        // 模擬健康檢查的邏輯
        return false; // 假設 API 2 是不可用的
    }
}

2. 組合多個 HealthIndicator(使用 CompositeHealthContributor

接下來,我們需要將這兩個健康檢查類組合在一起。CompositeHealthContributor 可以幫助我們組合多個 HealthIndicator

import org.springframework.boot.actuate.health.CompositeHealthContributor;
import org.springframework.boot.actuate.health.HealthContributor;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class CompositeHealthConfig {

    @Bean
    public HealthContributor combinedHealthIndicator(
            DownstreamApi1HealthIndicator api1HealthIndicator, 
            DownstreamApi2HealthIndicator api2HealthIndicator) {

        // 將多個 HealthIndicator 放入 Map 中
        Map<String, HealthIndicator> indicators = new LinkedHashMap<>();
        indicators.put("api1", api1HealthIndicator);
        indicators.put("api2", api2HealthIndicator);

        // 返回 CompositeHealthContributor 來組合它們
        return CompositeHealthContributor.fromMap(indicators);
    }
}
  • CompositeHealthContributor.fromMap() 方法允許你將多個健康檢查類組合在一起,並將它們以 Map 的形式註冊。Map 的鍵(例如 "api1""api2")會出現在 /actuator/health 的輸出中。

3. 訪問 /actuator/health

在啟動服務後,訪問 /actuator/health,你將看到組合後的健康狀態,類似如下的輸出:

{
    "status": "DOWN",
    "components": {
        "api1": {
            "status": "UP",
            "details": {
                "API 1": "Available"
            }
        },
        "api2": {
            "status": "DOWN",
            "details": {
                "API 2": "Unavailable"
            }
        }
    }
}
  • status 顯示的是組合後的狀態。因為其中一個下游 API (api2) 是 DOWN,所以整體的狀態是 DOWN

  • components 中列出了各個健康檢查類的具體狀態。

總結

  • 你可以透過 CompositeHealthContributor 組合多個健康檢查類(HealthIndicator),從而在 /actuator/health 中展示多個下游 API 或其他資源的健康狀況。
  • Spring Boot 會自動合併所有 HealthIndicatorCompositeHealthContributor,並將結果整合到健康檢查的輸出中。

相關文章