方式一:
為了定製 Spring Boot 的 Actuator 來實現你所描述的功能,即在呼叫自己的 /actuator/health
時,服務端能夠自動呼叫 4 個下游 API 的 /actuator/health
,並將其檢查結果與自己的健康狀態一起返回,可以按照以下步驟進行操作:
實現思路:
-
建立自定義的
HealthIndicator
:Spring Boot 提供了HealthIndicator
介面,允許你自定義健康檢查邏輯。我們可以透過實現該介面來定製對外部 API 的健康檢查。 -
整合多個 API 的健康狀態:在自定義的
HealthIndicator
實現中,我們可以發起 HTTP 請求呼叫 4 個下游 API 的健康檢查介面,獲取它們的健康狀態。 -
將各 API 的狀態與自身服務的健康狀態合併:透過
Health.Builder
將自身服務的健康狀態和 4 個下游 API 的健康檢查結果合併,返回給呼叫方。
詳細實現步驟:
1. 引入必要的依賴
確保你的 pom.xml
中包含以下依賴項,特別是用於發起 HTTP 請求的 spring-boot-starter-web
和 spring-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();
}
}
透過這種方式,你可以大大減少等待時間,從而提高整體的響應效率。
總結
- 透過實現自定義的
HealthIndicator
,你可以將下游 API 的健康檢查整合到自身服務的健康檢查中。 - 可以使用
RestTemplate
發起同步或非同步的 HTTP 請求,獲取下游 API 的健康狀態。 - 利用 Spring Boot 的自動發現機制,你的自定義
HealthIndicator
會被自動整合到/actuator/health
的輸出中。
方式二:
在 Spring Boot 中,你可以使用 組合多個 HealthIndicator
來執行多個健康檢查,並將它們的結果組合起來。Spring Boot 提供了一種方式來組合多個健康檢查,叫做 CompositeHealthContributor
。你可以透過實現多個 HealthIndicator
並將它們組合到一個 CompositeHealthContributor
中。
這裡是詳細步驟和示例程式碼來展示如何組合多個健康檢查:
實現步驟
-
實現多個
HealthIndicator
:首先,你需要為每個要檢查的下游 API 或其他資源實現各自的HealthIndicator
。 -
組合多個
HealthIndicator
:透過實現CompositeHealthContributor
,你可以將多個HealthIndicator
組合到一起。 -
整合到 Spring Boot Actuator:Spring Boot 會自動發現
HealthIndicator
和CompositeHealthContributor
,並將它們整合到/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 會自動合併所有
HealthIndicator
和CompositeHealthContributor
,並將結果整合到健康檢查的輸出中。