Spring Cloud Circuit Breaker
Spring Cloud 断路器为不同的断路器实现提供了一种抽象。它提供了一致的 API,可在应用程序中使用,令您这款们,作为开发人员,可以选择最适合您应用程序需要的断路器实现。
Core Concepts
要在代码中创建断路器,您可以使用 CircuitBreakerFactory
API。当您在类路径上包含 Spring Cloud 断路器启动器时,会为您自动创建一个实现此 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
。如果您不想提供备用方法,则可以选择将其排除在外。
Circuit Breakers In Reactive Code
如果类路径上有 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
Profiler,在断路器跳闸时将调用此函数,并且将传递导致失败的 Throwable
。
Configuration
您可以通过创建 Customizer
类型 的 Bean 来配置断路器。Customizer
接口具有一个(名为 customize
)方法,它采用要自定义的 Object
。
有关如何自定义给定实现的详细信息,请参阅以下文档:
一些 CircuitBreaker`实现(例如 `Resilience4JCircuitBreaker
)在每次调用 `CircuitBreaker#run`时都会调用 `customize`方法。这可能会效率低下。在这种情况下,可以使用 `CircuitBreaker#once`方法。对于在许多情况下调用 `customize`没有意义的情形(例如,在 consuming Resilience4j’s events的情况下),此方法非常有用。
以下示例展示了每个 io.github.resilience4j.circuitbreaker.CircuitBreaker
使用事件的方式。
Customizer.once(circuitBreaker -> {
circuitBreaker.getEventPublisher()
.onStateTransition(event -> log.info("{}: {}", event.getCircuitBreakerName(), event.getStateTransition()));
}, CircuitBreaker::getName)