当使用微服务架构来构建我们的应用程序时,在服务中最终会得到一个非常复杂的依赖树。如果依赖关系树中的服务遇到导致其开始缓慢响应的问题,则最终会形成一系列问题,这些问题会使依赖关系树级联起来。随着越来越多的请求进入应用程序,等待慢速服务响应可能会消耗越来越多的资源。更糟糕的是,对慢速服务施加的额外负载可能会加剧问题。为了帮助减轻这些类型的级联故障的影响,通常的做法是使用 断路器 作为微服务应用的一部分。
Spring Cloud 允许开发人员使用 Netflix Hystrix 作为 Spring Cloud Netflix项目的 一部分,为其应用 添加断路器 。除了Hystrix之外,Spring Cloud开发人员可能还想使用其他断路器实现。为了帮助Spring Cloud开发人员以一致的方式为其应用程序添加断路器,我们引入了 Spring Cloud Circuit Breaker项目 作为Spring Cloud孵化器的一部分。
Spring Cloud Circuit Breaker项目提供了一个抽象API,用于为您的应用添加断路器。在本博文发布时,有四种支持的实现:
要使用想要指定的实现,请将适当的 启动器 添加到应用程序的类路径中。
使用Spring Cloud断路器
目前,Spring Cloud Circuit Breaker不是Spring Cloud BOM的一部分,仅发布到我们的 快照仓库 。您需要将我们的快照仓库添加到Maven或Gradle文件中。以下示例使用Maven:
<repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https:<font><i>//repo.spring.io/libs-snapshot-local</url></i></font><font> <snapshots> <enabled><b>true</b></enabled> </snapshots> <releases> <enabled>false</enabled> </releases> </repository> </repositories> </font>
接下来,您需要将Spring Cloud Circuit Breaker依赖项添加到您的应用程序中。同样,以下示例使用Maven:
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId> spring-cloud-starter-circuitbreaker-resilience4j </artifactId> <version>0.0.1.BUILD-SNAPSHOT</version> </dependency> </dependencies>
Spring Cloud Circuit Breaker CircuitBreakerFactory根据应用程序类路径上的启动器自动配置实现。然后,您可以将此接口注入到所需的任何类中。以下示例显示了如何执行此操作:
@Service <b>public</b> <b>static</b> <b>class</b> DemoControllerService { <b>private</b> RestTemplate <b>rest</b>; <b>private</b> CircuitBreakerFactory cbFactory; <b>public</b> DemoControllerService(RestTemplate <b>rest</b>, CircuitBreakerFactory cbFactory) { <b>this</b>.<b>rest</b> = <b>rest</b>; <b>this</b>.cbFactory = cbFactory; } <b>public</b> String slow() { <b>return</b> cbFactory.create(<font>"slow"</font><font>).run(() -> <b>rest</b>.getForObject(</font><font>"/slow"</font><font>, String.<b>class</b>), throwable -> </font><font>"fallback"</font><font>); } } </font>
大多数实现还支持Reactive API。目前,Spring Retry是唯一的没有反应式实现。如果要在断路器中包含一些代反应式码,则需要使用ReactiveCircuitBreakerFactory。以下示例显示了如何执行此操作:
@Service <b>public</b> <b>static</b> <b>class</b> DemoControllerService { <b>private</b> ReactiveCircuitBreakerFactory cbFactory; <b>private</b> WebClient webClient; <b>public</b> DemoControllerService(WebClient webClient, ReactiveCircuitBreakerFactory cbFactory) { <b>this</b>.webClient = webClient; <b>this</b>.cbFactory = cbFactory; } <b>public</b> Mono<String> slow() { <b>return</b> webClient.get().uri(<font>"/slow"</font><font>).retrieve() .bodyToMono(String.<b>class</b>).transform(it -> { CircuitBreaker cb = cbFactory.create(</font><font>"slow"</font><font>); <b>return</b> cb.run(it, throwable -> Mono.just(</font><font>"fallback"</font><font>)); }); } } </font>
配置断路器
在大多数情况下,您将需要配置断路器的行为。为此,您可以创建类型的bean Customizer。Spring Cloud断路器允许您为所有断路器提供默认配置以及特定断路器的配置。例如,要在使用Resilience4J时为所有断路器提供默认配置,您可以将以下bean添加到配置类:
@Bean <b>public</b> Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() { <b>return</b> factory -> factory.configureDefault( id -> <b>new</b> Resilience4JConfigBuilder(id) .timeLimiterConfig(TimeLimiterConfig.custom() .timeoutDuration(Duration.ofSeconds(4)).build()) .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults()) .build()); }
配置单个断路器的代码和上面看起来非常相似,另外您需要在Customizer其中提供断路器ID ,如下所示:
@Bean <b>public</b> Customizer<Resilience4JCircuitBreakerFactory> slowCustomizer() { <b>return</b> factory -> factory.configure(builder -> { <b>return</b> builder .timeLimiterConfig(TimeLimiterConfig.custom() .timeoutDuration(Duration.ofSeconds(2)).build()) .circuitBreakerConfig( CircuitBreakerConfig.ofDefaults()); }, <font>"slow"</font><font>); } </font>
我们期待听到您对这个新项目的看法。查看 GitHub项目 以及 文档 以获取更多信息。与往常一样,您可以通过 Stack Overflow 和 Gitter 或通过创建 GitHub问题与我们联系 。