
认知科技技术团队
认知科技技术团队,定期提供最新IT类资讯、原创内容、编程开发的教程与经验分享,福利天天在等你!
288篇原创内容
公众号
翻译自:https://dzone.com/articles/circuit-breaker-pattern-resilient-systems
可靠性至关重要,特别是当服务相互依赖时,一个组件的失败可能会对其他服务产生连锁反应。熔断器模式(Circuit Breaker Pattern)是一种用于构建容错和弹性系统的重要设计模式,尤其在微服务架构中。本文解释了熔断器模式的基础知识、其好处以及如何实现它以保护系统免受失败影响。
软件中的熔断器模式实际上受到家用电气熔断器的启发,电气熔断器通过检测故障并在问题发生时停止电力流动来防止系统故障。在软件中,这种模式监控服务交互,防止持续调用 / 重试失败的服务,从而避免对该服务造成过载问题。通过“切断”服务之间的电路,这种模式允许系统优雅地处理失败并避免连锁问题。
显示熔断器模式不同状态的状态图
熔断器(circuit breaker)有三个明显状态:闭合、打开和半开(Closed, Open, and Half-Open)。
闭合状态(Closed) :通常,熔断器是“闭合”的,意味着(电路闭合)服务之间如往常一样流动请求。(用电气术语来说,电线连接以允许电力流动)
打开状态(Open) :当熔断器打开时,它立即拒绝前往失败服务的请求,防止进一步对服务施加压力,并给予其恢复时间。在此期间,可以触发回退机制,例如返回缓存数据或默认响应。
半开状态(Half-Open) :在定义的超时后,熔断器切换到半开状态,允许从终端发出一定数量的请求以确定服务是否已恢复。如果请求成功,熔断器再次闭合;但如果失败,则回到打开状态。
这种设计模式的主要思想是防止失败的服务拖垮整个系统,并在服务恢复健康后提供恢复的方式。
电气类比以记住打开和闭合状态
在复杂的分布式系统中,失败是不可避免的。以下是一些熔断器模式至关重要的实际原因:
防止连锁失败 :在微服务架构中,如果一个服务失败而其他服务依赖于它,失败可能会蔓延到整个系统。熔断器通过隔离故障服务来阻止这种情况。
提高系统稳定性 :通过停止前往失败服务的请求,熔断器防止资源耗尽并降低对依赖服务的负载,从而帮助稳定系统。
更好的用户体验(UX) :与其让请求长时间卡住或返回未处理的错误,熔断器允许通过提供回退响应来实现优雅降级,即使在失败期间也能改善用户体验。
自动恢复 :半开状态允许系统自动测试服务的健康状况并在无需手动干预的情况下恢复。
熔断器模式的实现取决于你所使用的特定技术栈,但标准方法保持不变。以下是实现它的高级概述:
以下示例展示了如何使用广泛采用的 Resilience4j 库在 Java 中实现熔断器:
Resilience4j 是一个强大的 Java 库,旨在帮助你实现弹性模式,如熔断器、速率限制器、重试、隔舱模式和时间限制器。Resilience4j 的主要优势之一是其灵活性和易于配置。正确配置这些弹性模式可以使开发人员微调系统,以实现最大容错性、改善稳定性和在面对错误时更好的性能。
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import java.time.Duration;
public class CircuitBreakerExample {
public static void main(String[] args) {
// 为熔断器创建自定义配置
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofSeconds(5))
.ringBufferSizeInHalfOpenState(5)
.ringBufferSizeInClosedState(20)
.build();
// 使用自定义全局配置创建熔断器注册表
CircuitBreakerRegistry registry = CircuitBreakerRegistry.of(config);
// 从熔断器注册表中获取或创建熔断器
CircuitBreaker circuitBreaker = registry.circuitBreaker("myService");
// 用熔断器装饰服务调用
Supplier<String> decoratedSupplier = CircuitBreaker
.decorateSupplier(circuitBreaker, myService::call);
// 执行装饰后的供应商并处理结果
Try<String> result = Try.ofSupplier(decoratedSupplier)
.recover(throwable -> "Fallback response");
System.out.println(result.get());
}
}
在此示例中,熔断器配置为在 50% 的请求失败时打开。它保持打开状态 5 秒,然后进入半开状态,在此期间允许 5 个请求来测试服务。如果请求成功,它闭合熔断器,允许恢复正常操作。
Resilience4j 提供了灵活且强大的熔断器模式实现,允许开发人员配置各个方面以适应应用程序的需求。正确配置对于平衡容错性、系统稳定性和恢复机制至关重要。以下是 Resilience4j 熔断器的关键配置选项:
1. 失败率阈值: 这是导致熔断器从闭合状态(正常操作)过渡到打开状态(阻止请求)的失败请求的百分比。目的是控制熔断器何时停止将请求转发到失败的服务。例如,50% 的阈值意味着在一半请求失败后熔断器将打开。
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50) // 在 50% 的请求失败时打开电路
.build();
2. 打开状态等待时长: 熔断器在进入半开状态(开始允许有限数量的请求以测试服务是否已恢复)之前保持在打开状态的时间。这防止立即重试失败的服务,允许下游服务在再次测试之前有时间恢复。
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.waitDurationInOpenState(Duration.ofSeconds(30)) // 在转换到半开状态之前等待 30 秒
.build();
3. 闭合状态环形缓冲区大小: 熔断器在闭合状态下记录的请求数量(在评估失败率之前)。这作为错误监控的滑动窗口。较大的环形缓冲区大小意味着在决定是否打开电路时会考虑更多的数据点。
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.ringBufferSizeInClosedState(50) // 考虑最后 50 个请求来计算失败率
.build();
4. 半开状态环形缓冲区大小: 在半开状态下允许的请求数量,然后根据成功或失败率决定是闭合电路还是返回到打开状态。确定在半开状态下测试多少个请求以决定服务是否稳定到足以闭合电路,或者是否仍在失败。
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.ringBufferSizeInHalfOpenState(5) // 在半开状态下测试 5 个请求
.build();
5. 滑动窗口类型和大小: 定义如何测量失败率:要么是基于计数的滑动窗口,要么是基于时间的滑动窗口。提供了在处理失败率计算时的灵活性。基于计数的窗口在高流量系统中很有用,而基于时间的窗口在低流量环境中表现出色。
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.slidingWindowType(SlidingWindowType.COUNT_BASED)
.slidingWindowSize(100) // 使用最后 100 个请求的基于计数的窗口
.build();
6. 最少调用次数: 指定在评估失败率之前所需的最少请求数。 防止熔断器在没有足够数据来计算有意义的失败率时过早打开,特别是在低流量期间。
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.minimumNumberOfCalls(20) // 要求至少 20 个调用后才评估失败率
.build();
7. 半开状态允许的调用次数: 在半开状态下允许通过的请求数量,以检查服务是否已恢复。在转换到半开状态后,此配置控制允许多少个请求来评估服务恢复情况。较小的值可以更快地发现 issues,而较大的值可以确保临时问题不会导致电路重新打开。
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.permittedNumberOfCallsInHalfOpenState(5) // 用 5 个请求测试恢复情况
.build();
8. 慢调用持续时间阈值: 定义慢调用的阈值。超过此阈值的调用被视为“慢”调用,并可能对失败率有所贡献。
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.slowCallDurationThreshold(Duration.ofSeconds(2)) // 任何超过 2 秒的调用都被视为慢调用
.build();
9. 慢调用率阈值: 触发熔断器打开的“慢”调用的百分比,类似于失败率阈值。检测性能逐渐下降的服务,在其完全失败之前允许系统提前响应性能问题。
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.slowCallRateThreshold(50) // 当 50% 的调用变慢时打开电路
.build();
10. 从打开到半开的自动转换: 控制熔断器在经过设定的等待时长后如何自动从打开状态转换到半开状态。通过定期测试服务,使系统能够自动恢复,避免手动干预的需要。
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.automaticTransitionFromOpenToHalfOpenEnabled(true) // 启用自动转换
.build();
11. 回退机制: 帮助在熔断器打开且请求被阻止时配置回退操作。防止连锁失败并通过提供缓存数据 / 默认响应来改善用户体验。
Try<String> result = Try.ofSupplier(
CircuitBreaker.decorateSupplier(circuitBreaker, service::call)
).recover(throwable -> "Fallback response");
熔断器模式(Circuit Breaker Pattern)是构建弹性、容错系统的重要工具。通过防止连锁失败、提高系统稳定性并启用优雅恢复,它在现代软件架构中,特别是在微服务环境中,发挥着关键作用。无论你是构建大型企业级应用程序还是较小的分布式系统,熔断器都可以在维护失败条件下的可靠操作方面成为改变游戏规则的存在。