Spring Cloud Circuit Breaker

Spring Cloud Circuit Breaker 提供了跨不同断路器实现的抽象。它为您的应用程序提供了一致的 API,让您(开发者)能够根据自身应用需求选择最适合的断路器实现。spring-doc.cadn.net.cn

核心概念

使用代码中的熔断器,您可以使用CircuitBreakerFactoryAPI。 在类路径中包含SpringCloudCircuitBreakerStarters时,会自动为您创建实现该API的bean。 下面的示例显示了如何使用此API的一个简单示例:spring-doc.cadn.net.cn

@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 是当熔断器触发时所执行的回退(fallback)逻辑。
该函数会接收导致回退被触发的 Throwable(即异常或错误信息)。
您可以选择性地省略回退逻辑,如果您不希望提供回退处理。spring-doc.cadn.net.cn

断路器在响应式代码中

如果 Project Reactor 在类路径中,您还可以在响应式代码中使用 ReactiveCircuitBreakerFactory。以下示例展示了如何实现此操作:spring-doc.cadn.net.cn

@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 方法接收一个 MonoFlux,并将其封装在断路器中。您可以选择对备用方法 Function 进行性能分析,当断路器被触发时将调用此方法,并将导致失败的 Throwable 作为参数传入。spring-doc.cadn.net.cn

配置

您可以通过创建类型为 Customizer 的 Bean 来配置熔断器。 Customizer 接口包含一个单一方法(称为 customize),该方法用于自定义 Objectspring-doc.cadn.net.cn

有关如何自定义给定实现的详细信息,请参见以下文档:spring-doc.cadn.net.cn

一些 CircuitBreaker 实现类例如 Resilience4JCircuitBreaker 每次调用 customize 方法时都会调用 CircuitBreaker#run。这可能会造成低效。在这种情况下,您可以使用 CircuitBreaker#once 方法。当多次调用 customize 没有意义时很有用,比如在[消费Resilience4j事件](6)的情况下。spring-doc.cadn.net.cn

以下示例展示了每个io.github.resilience4j.circuitbreaker.CircuitBreaker消耗事件的方式。spring-doc.cadn.net.cn

Customizer.once(circuitBreaker -> {
  circuitBreaker.getEventPublisher()
    .onStateTransition(event -> log.info("{}: {}", event.getCircuitBreakerName(), event.getStateTransition()));
}, CircuitBreaker::getName)

支持用于开发 Spring 框架的HTTP服务客户端

Spring Cloud 通过以下配置器为 Spring HTTP 服务客户端集成提供支持:spring-doc.cadn.net.cn

这些配置器为 Spring HTTP 服务客户端组 启用了断路器支持。spring-doc.cadn.net.cn

当使用@HttpServiceFallbackAnnotation配置回退类时, 断路器适配器装饰器被添加: - CircuitBreakerAdapterDecoratorRestClient一起使用 - ReactiveCircuitBreakerAdapterDecoratorWebClient一起使用spring-doc.cadn.net.cn

通过设置相应的属性,可以禁用HTTP服务客户端的断路器集成:spring-doc.cadn.net.cn

  • 对于阻塞客户端(RestClient): spring.cloud.circuitbreaker.http-services.enabled=falsespring-doc.cadn.net.cn

  • 对于响应式(WebClient)客户端:spring.cloud.circuitbreaker.reactive-http-services.enabled=falsespring-doc.cadn.net.cn

这可以防止将断路器装饰器应用于基于接口的 HTTP 客户端组。spring-doc.cadn.net.cn

使用注解声明回退

回退是通过在配置类上使用@HttpServiceFallback注解来配置的。这个注解允许您声明:spring-doc.cadn.net.cn

可以使用 Java 的 @Repeatable 注解机制在同一个类上声明多个 @HttpServiceFallback 注解。
如果未指定组,则回退适用于所有没有为给定服务接口显式配置每组回退的组。spring-doc.cadn.net.cn

回退类使用以下优先级进行解析:spring-doc.cadn.net.cn

  1. 一个回退类,同时匹配 forServiceforGroupspring-doc.cadn.net.cn

  2. 具有匹配forService且无forGroup(服务的全局回退)的回退类spring-doc.cadn.net.cn

  3. 一个回退类,不包含 forServiceforGroup(组或全局默认所有服务)spring-doc.cadn.net.cn

例举

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

此配置的结果是:spring-doc.cadn.net.cn

断路器适配器的工作原理

适配器使用断路器逻辑包装@HttpExchange方法调用。当触发回退时,将使用用户定义的回退类创建代理。通过匹配选择适当的回退方法:spring-doc.cadn.net.cn

  • 具有相同名称和参数类型的spring-doc.cadn.net.cn

  • 一个方法,其名称和参数类型与前面的方法相同,并且在参数列表中增加了一个Throwable参数(用于访问失败的原因)spring-doc.cadn.net.cn

给定以下接口:spring-doc.cadn.net.cn

@HttpExchange("/test")
public interface TestService {

    @GetExchange("/{id}")
    Person test(@PathVariable UUID id);

    @GetExchange
    String test();
}

可能匹配的回退类是:spring-doc.cadn.net.cn

public class TestServiceFallback {

    public Person test(UUID id);

    public String test(Throwable cause);
}