|
此版本仍在开发中,目前尚不被视为稳定版本。如需最新稳定版本,请使用 Spring Cloud Commons 5.0.1! |
Spring Cloud Circuit Breaker
Spring Cloud Circuit Breaker 提供了跨不同断路器实现的抽象。它为您的应用程序提供了一致的 API,让您(开发者)能够根据自身应用需求选择最适合的断路器实现。
核心概念
使用代码中的熔断器,您可以使用CircuitBreakerFactoryAPI。
在类路径中包含SpringCloudCircuitBreakerStarters时,会自动为您创建实现该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 是当熔断器触发时所执行的回退(fallback)逻辑。
该函数会接收导致回退被触发的 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 每次调用 customize 方法时都会调用 CircuitBreaker#run。这可能会造成低效。在这种情况下,您可以使用 CircuitBreaker#once 方法。当多次调用 customize 没有意义时很有用,比如在[消费Resilience4j事件](6)的情况下。
以下示例展示了每个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);
}