Spring Cloud Circuit Breaker
Spring Cloud 斷路器為不同的斷路器實現提供了抽象。它提供了一致的 API 供您的應用程式使用,讓開發人員可以選擇最適合其應用程式需求的斷路器實現。
核心概念
要在程式碼中建立斷路器,可以使用 CircuitBreakerFactory API。當您在類路徑中包含 Spring Cloud 斷路器 starter 時,會自動為您建立一個實現此 API 的 bean。以下示例展示瞭如何使用此 API 的簡單示例
@Service
public static class DemoControllerService {
private RestTemplate rest;
private CircuitBreakerFactory cbFactory;
public DemoControllerService(RestTemplate rest, CircuitBreakerFactory cbFactory) {
this.rest = rest;
this.cbFactory = cbFactory;
}
public String slow() {
return cbFactory.create("slow").run(() -> rest.getForObject("/slow", String.class), throwable -> "fallback");
}
}
CircuitBreakerFactory.create API 建立一個名為 CircuitBreaker 的類的例項。run 方法接受一個 Supplier 和一個 Function。Supplier 是您將封裝在斷路器中的程式碼。Function 是斷路器跳閘時執行的備用方法。該函式會傳遞導致備用方法觸發的 Throwable。如果您不想提供備用方法,可以選擇排除它。
響應式程式碼中的斷路器
如果 Project Reactor 位於類路徑中,您還可以將 ReactiveCircuitBreakerFactory 用於您的響應式程式碼。以下示例展示瞭如何實現
@Service
public static class DemoControllerService {
private ReactiveCircuitBreakerFactory cbFactory;
private WebClient webClient;
public DemoControllerService(WebClient webClient, ReactiveCircuitBreakerFactory cbFactory) {
this.webClient = webClient;
this.cbFactory = cbFactory;
}
public Mono<String> slow() {
return webClient.get().uri("/slow").retrieve().bodyToMono(String.class).transform(
it -> cbFactory.create("slow").run(it, throwable -> return Mono.just("fallback")));
}
}
ReactiveCircuitBreakerFactory.create API 建立一個名為 ReactiveCircuitBreaker 的類的例項。run 方法接受一個 Mono 或一個 Flux 並將其封裝在斷路器中。您可以選擇提供一個備用 Function,如果斷路器跳閘,它將被呼叫,並傳遞導致故障的 Throwable。
配置
您可以透過建立 Customizer 型別的 bean 來配置您的斷路器。Customizer 介面有一個方法(名為 customize),它接受要自定義的 Object。
有關如何自定義給定實現的詳細資訊,請參閱以下文件
某些 CircuitBreaker 實現,例如 Resilience4JCircuitBreaker,每次呼叫 CircuitBreaker#run 時都會呼叫 customize 方法。這可能會效率低下。在這種情況下,您可以使用 CircuitBreaker#once 方法。這在多次呼叫 customize 沒有意義的情況下很有用,例如,在 消費 Resilience4j 的事件 的情況下。
以下示例展示了每個 io.github.resilience4j.circuitbreaker.CircuitBreaker 消費事件的方式。
Customizer.once(circuitBreaker -> {
circuitBreaker.getEventPublisher()
.onStateTransition(event -> log.info("{}: {}", event.getCircuitBreakerName(), event.getStateTransition()));
}, CircuitBreaker::getName)
Spring HTTP 服務客戶端支援
Spring Cloud 透過以下配置器支援 Spring HTTP 服務客戶端整合
-
CircuitBreakerRestClientHttpServiceGroupConfigurer -
CircuitBreakerWebClientHttpServiceGroupConfigurer
這些配置器為 Spring HTTP 服務客戶端組 啟用斷路器支援。
當使用 @HttpServiceFallbackAnnotation 配置備用類時,會新增斷路器介面卡裝飾器:- CircuitBreakerAdapterDecorator 用於 RestClient - ReactiveCircuitBreakerAdapterDecorator 用於 WebClient
|
您可以透過設定相應的屬性來停用 HTTP 服務客戶端的斷路器整合
這會阻止斷路器裝飾器應用於基於介面的 HTTP 客戶端組。 |
使用註解宣告備用
備用透過配置類上的 @HttpServiceFallback 註解進行配置。此註解允許您宣告
-
備用實現類(透過
value) -
備用支援的服務介面(透過
forService,可選) -
備用適用的組(透過
forGroup,可選)
可以使用 Java 的 @Repeatable 註解機制在同一個類上宣告多個 @HttpServiceFallback 註解。如果未指定組,則備用適用於所有沒有給定服務介面的顯式每組備用的組。
備用類按以下優先順序解析
-
同時匹配
forService和forGroup的備用類 -
匹配
forService但沒有forGroup的備用類(服務的全域性備用) -
既沒有
forService也沒有forGroup的備用類(組中所有服務或全域性的預設備用)
示例
@HttpServiceFallback(value = DefaultFallbacks.class)
@HttpServiceFallback(value = GroupAndServiceSpecificFallbacks.class, service = {BillingService.class, ShippingService.class}, group = "billing")
public class MyFallbackConfig {
...
}
此配置導致
-
DefaultFallbacks用作所有未明確處理的服務的全域性備用 -
GroupAndServiceSpecificFallbacks僅用於"billing"組中的BillingService和ShippingService
|
斷路器介面卡的工作原理
介面卡使用斷路器邏輯封裝 @HttpExchange 方法呼叫。當備用被觸發時,使用使用者定義的備用類建立一個代理。透過匹配選擇適當的備用方法
-
具有相同名稱和引數型別的方法,或
-
具有相同名稱和引數型別,前面帶有一個
Throwable引數(用於訪問失敗原因)的方法
給定以下介面
@HttpExchange("/test")
public interface TestService {
@GetExchange("/{id}")
Person test(@PathVariable UUID id);
@GetExchange
String test();
}
匹配的備用類可以是
public class TestServiceFallback {
public Person test(UUID id);
public String test(Throwable cause);
}