|
此版本仍在开发中,目前尚不被视为稳定版本。如需最新稳定版本,请使用 Spring Cloud Commons 5.0.1! |
Spring Cloud Circuit Breaker
Spring Cloud Circuit Breaker 提供了跨不同断路器实现的抽象。它为您的应用程序提供了一致的 API,让您(开发者)能够根据自身应用需求选择最适合的断路器实现。
核心概念
要在您的代码中创建断路器,可以使用 CircuitBreakerFactory API。当您在类路径中包含 Spring Cloud Circuit Breaker Starters时,系统会自动为您创建一个实现此 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)在每次调用 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)