介绍 Spring Cloud Circuit Breaker

工程 | Ryan Baxter | 2019年4月16日 | ...

背景

在使用微服务架构构建应用时,服务之间常常形成相当复杂的依赖树。如果依赖树下游的服务遇到导致其响应缓慢的问题,最终会导致一系列问题向上游依赖树蔓延。随着越来越多的请求进入应用,等待慢速服务响应可能会消耗越来越多的资源。更糟糕的是,慢速服务上增加的负载可能会加剧问题。为了缓解这类级联故障的影响,在微服务应用中使用断路器是一种常见做法。

Spring Cloud 通过将Netflix Hystrix 作为Spring Cloud Netflix 项目的一部分,让开发者能够向其应用添加断路器。除了 Hystrix,Spring Cloud 开发者可能还想使用其他断路器实现。为了帮助 Spring Cloud 开发者以一致的方式向其应用添加断路器,我们推出了 Spring Cloud 断路器项目,作为 Spring Cloud 孵化器的一部分。

关于

Spring Cloud 断路器项目提供了一个抽象 API,用于向应用添加断路器。截至本博文发布时,支持四种实现

要使用特定的实现,请将相应的 starter 添加到应用的 classpath 中。

使用 Spring Cloud 断路器

目前,Spring Cloud 断路器不是 Spring Cloud BOM 的一部分,并且仅发布到我们的 snapshot 仓库。您需要将我们的 snapshot 仓库添加到您的 Maven 或 Gradle 文件中。以下示例使用 Maven

<repositories>
    <repository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>https://repo.spring.io/libs-snapshot-local</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
        <releases>
            <enabled>false</enabled>
        </releases>
    </repository>
</repositories>

接下来,您需要将 Spring Cloud 断路器依赖项添加到您的应用中。同样,以下示例使用 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 断路器根据应用 classpath 中的 starter 自动配置一个 CircuitBreakerFactory 的实现。然后,您可以将此接口注入到任何所需的类中。以下示例展示了如何进行

@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");
	}
}

大多数实现也支持 Reactive API。目前,Spring Retry 是唯一没有响应式实现的实现。如果您想将一些响应式代码包装在断路器中,您需要使用 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 -> {
			CircuitBreaker cb = cbFactory.create("slow");
			return cb.run(it, throwable -> 
                            Mono.just("fallback"));
                });
	}
}

配置断路器

在大多数情况下,您会希望配置断路器的行为。为此,您可以创建类型为 Customizer 的 bean。Spring Cloud 断路器允许您为所有断路器提供默认配置,以及为特定断路器提供配置。例如,在使用 Resilience4J 时,要为所有断路器提供默认配置,您可以将以下 bean 添加到配置类中

@Bean
public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
	return factory -> factory.configureDefault(
            id -> new Resilience4JConfigBuilder(id)
            .timeLimiterConfig(TimeLimiterConfig.custom()
                .timeoutDuration(Duration.ofSeconds(4)).build())
            .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
            .build());
}

配置单个断路器的代码非常相似,只是您需要在 Customizer 中提供一个断路器 ID,如下所示

@Bean
public Customizer<Resilience4JCircuitBreakerFactory> slowCustomizer() {
	return factory -> factory.configure(builder -> {
		return builder
			.timeLimiterConfig(TimeLimiterConfig.custom()
                            .timeoutDuration(Duration.ofSeconds(2)).build())
			.circuitBreakerConfig(
                            CircuitBreakerConfig.ofDefaults());
	}, "slow");
}

反馈

我们期待听到您对这个新项目的看法。请查看 GitHub 项目 以及 文档 以获取更多信息。一如既往,您可以通过 Stack OverflowGitter 联系我们,或者创建 GitHub issue

获取 Spring 新闻通讯

订阅 Spring 新闻通讯,保持联系

订阅

领先一步

VMware 提供培训和认证,为您的进步加速。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看全部