Spring Cloud Circuit Breaker

Spring Cloud 斷路器為不同的斷路器實現提供了抽象。它提供了一致的 API 供您的應用程式使用,讓開發人員可以選擇最適合其應用程式需求的斷路器實現。

支援的實現

Spring Cloud 支援以下斷路器實現

核心概念

要在程式碼中建立斷路器,可以使用 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 和一個 FunctionSupplier 是您將封裝在斷路器中的程式碼。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 服務客戶端的斷路器整合

  • 對於阻塞 (RestClient) 客戶端:spring.cloud.circuitbreaker.http-services.enabled=false

  • 對於響應式 (WebClient) 客戶端:spring.cloud.circuitbreaker.reactive-http-services.enabled=false

這會阻止斷路器裝飾器應用於基於介面的 HTTP 客戶端組。

使用註解宣告備用

備用透過配置類上的 @HttpServiceFallback 註解進行配置。此註解允許您宣告

  • 備用實現類(透過 value

  • 備用支援的服務介面(透過 forService,可選)

  • 備用適用的組(透過 forGroup,可選)

可以使用 Java 的 @Repeatable 註解機制在同一個類上宣告多個 @HttpServiceFallback 註解。如果未指定組,則備用適用於所有沒有給定服務介面的顯式每組備用的組。

備用類按以下優先順序解析

  1. 同時匹配 forServiceforGroup 的備用類

  2. 匹配 forService 但沒有 forGroup 的備用類(服務的全域性備用)

  3. 既沒有 forService 也沒有 forGroup 的備用類(組中所有服務或全域性的預設備用)

示例

@HttpServiceFallback(value = DefaultFallbacks.class)
@HttpServiceFallback(value = GroupAndServiceSpecificFallbacks.class, service = {BillingService.class, ShippingService.class}, group = "billing")
public class MyFallbackConfig {
    ...
}

此配置導致

  • DefaultFallbacks 用作所有未明確處理的服務的全域性備用

  • GroupAndServiceSpecificFallbacks 僅用於 "billing" 組中的 BillingServiceShippingService

  • 備用類及其方法必須是 public

  • 備用方法不得使用 @HttpExchange 註解

斷路器介面卡的工作原理

介面卡使用斷路器邏輯封裝 @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);
}
© . This site is unofficial and not affiliated with VMware.