@CircuitBreaker 是Spring Retry 包中提供的熔断相关的功能。它是在 @Retryable 的基础上实现的。所以大家在看这篇文章之前可以先回顾下之前我们分析的 spring Retry 中关于 @Retryable 的相关功能:
对 @Retryable 的原理了解之后,我们一起来学习下 @CircuitBreaker。
@CircuitBreaker 用法
首先,我们看下 @CircuitBreaker 的简单用法

这样,我们就可以实现一个简单的熔断器了,重试 3 次之后则启动熔断功能。@CircuitBreaker 还有很多复杂的用法提供给我们使用,我们一起来看下吧!
@CircuitBreaker 注解
接下来,我们看下 @CircuitBreaker 注解的相关方法

图中 ① 是一个 @Retryable(stateful = true) 注解,它表示 @CircuitBreaker 注解继承了 @Retryable 注解,并且 stateful 方法是 true,说明 @CircuitBreaker 是一个有状态的 @Retryable。
所以,我们也可以看到 图中 ② 标识的方法是 @Retryable 的,这也就是刚刚我提到 @CircuitBreaker 是在 @Retryable 基础上的实现的原因。当然在原理分析中我们也会提到。
然后图中 ③ 和 ④ 就是 @CircuitBreaker 中特有的方法了,大家可以通过注释了解这些方法的作用。
@CircuitBreaker 原理
@Retryable 的文章中我们有讲到,处理 @Retryable 注解的代理时,提到过下面的代码

在 @Retryable 的文章中,我们 分析了 ③ 处的代码,由于 @CircuitBreaker 是有状态的重试,所以我们要看的是② 处的 getStatefulInterceptor 相关处理。

我们主要看 circuit 不为空的情况,可以看到 circuit 不为空的时候最后使用 StatefulRetryOperationsInterceptor 来处理 @CircuitBreaker,而最终处理熔断或者重试都会执行 RetryTemplate 中的 doExecute 方法,这个方法我们关于 @Retryable 的文章中已经分析过了,判断是否可以重试主要依赖相关 RetryPolicy 的 canRetry 及其他相关方法,那么接下来我们就看看 处理 @CircuitBreaker 的重试策略 CircuitBreakerRetryPolicy 吧。
CircuitBreakerRetryPolicy

从上面的代码,可以看到,canRetry 的核心其实是 circuit.isOpen(),判断熔断开关是否开启,如果是关闭状态的话,熔断策略其实就退化成了我们配置的 Retry 的相关策略。那我们就继续看下熔断开关的相关逻辑吧。

从代码可以看到
- 当重试失败,且在熔断器打开时间窗口[0,openWindow) 内,立即熔断;
- 当重试失败,且在指定超时时间后(>timeout),熔断器电路重新闭合;
- 在熔断器半打开状态[openWindow, timeout] 时,只要重试成功则重置上下文,断路器闭合。
到这里,@CircuitBreaker 的相关代码我们就分析完了,@CircuitBreaker 提供的功能已比较强大,而且我们也可以通过 Spring Retry 包中提供的相关接口做自定义的实现,应该可以满足我们业务中的大部分场景了。关于更加强大的熔断工具 hystrix,我们之后再进行分析。希望这边文章可以帮助到大家。
欢迎关注我的公众号“shy先生”,很高兴能与大家一起成长。