断路器
熔断器 使您能够通过暂时禁用执行来创建快速失败的系统,以防止系统过载。有两种类型的熔断器:基于计数的 和 基于时间的。基于计数的 熔断器通过跟踪最近的执行结果来工作,直到达到某个限制。基于时间的 熔断器通过跟踪在一段时间内发生的任何数量的执行结果来工作。
创建一个断路器非常简单,例如:
// Opens after 5 failures, half-opens after 1 minute, closes after 2 successes
CircuitBreaker<Object> breaker = CircuitBreaker.builder()
.handle(ConnectException.class)
.withFailureThreshold(5)
.withDelay(Duration.ofMinutes(1))
.withSuccessThreshold(2)
.build();
工作原理
当最近执行失败的次数超过配置的阈值时,断路器会打开,进一步的执行将会失败,并且会CircuitBreakerOpenException。经过一段时间延迟后,断路器会半打开,允许进行试执行,以决定断路器是否应该关闭或再次打开。如果试执行达到了成功阈值,断路器会再次关闭,执行将恢复正常进行,否则会再次打开。
配置
断路器 可以灵活配置以表达断路器应在何时断开、半断开和闭合。
打开
断路器是基于计数的,默认情况下,当发生一次故障后,它将打开。相反,您可以将断路器配置为当连续执行的次数失败时打开:
builder.withFailureThreshold(5);
例如,当最近的5次执行中有3次失败时:
builder.withFailureThreshold(3, 5);
一个基于时间的断路器可以配置为在一定时间内发生多次故障时打开:
builder.withFailureThreshold(3, Duration.ofMinutes(1));
或者在一段时间内,执行次数达到最低次数后发生一定数量的失败:
builder.withFailureThreshold(3, 5, Duration.ofMinutes(1));
它还可以配置为在执行次数达到最低次数后,失败率超过阈值时打开:
builder.withFailureRateThreshold(20, 5, Duration.ofMinutes(1));
半开
打开后,断路器默认会延迟1分钟,然后转换到半开状态。您可以配置不同的延迟:
builder.withDelay(Duration.ofSeconds(30));
或者一个基于执行结果的计算延迟。
关闭
断路器可以配置为关闭,如果多次试执行成功,否则它将重新打开:
builder.withSuccessThreshold(5);
断路器也可以配置为重新关闭,例如,如果在最近的5次执行中有3次成功,则重新打开,否则:
builder.withSuccessThreshold(3, 5);
如果没有配置成功阈值,则会使用失败阈值来确定断路器是否应从半开状态转换为关闭或打开状态。
故障处理
断路器可以被配置为仅处理某些结果或异常,结合上面描述的任何配置:
builder
.handle(ConnectException.class)
.handleResult(null);
事件监听器
除了标准的策略监听器,断路器可以通知您断路器的状态发生变化:
builder
.onOpen(e -> log.info("The circuit breaker was opened"))
.onClose(e -> log.info("The circuit breaker was closed"))
.onHalfOpen(e -> log.info("The circuit breaker was half-opened"));
指标
断路器 可以提供断路器当前状态的指标,包括 执行次数、成功次数、失败次数、成功率 和 失败率。当处于 打开 状态时,它还可以返回 剩余延迟。
最佳实践
断路器可以并且应该在访问相同依赖项的代码之间共享。这确保了如果断路器打开,所有共享相同依赖项并使用相同断路器的执行将被阻止,直到电路再次闭合。例如,如果对同一外部服务器进行多个连接或请求,通常它们应该都通过相同的断路器。
独立使用
一个断路器也可以以独立方式手动操作:
breaker.open();
breaker.halfOpen();
breaker.close();
if (breaker.tryAcquirePermit()) {
try {
doSomething();
breaker.recordSuccess();
} catch (Exception e) {
breaker.recordException(e);
}
}
基于时间的解决方案
基于时间 熔断器使用滑动窗口来聚合执行结果。随着时间的推移和新结果的记录,较旧的结果将被丢弃。为了保持空间和时间效率,结果被分组到10个时间片中,每个时间片代表配置的故障阈值期的1/10。当时间片不再在阈值期内时,其结果将被丢弃。这使得熔断器可以基于最近的结果进行操作,而无需跟踪每个单独执行的时间。
性能
Failsafe 的内部 断路器 实现是空间和时间高效的,使用一个循环数据结构来记录执行结果。记录执行和评估阈值的时间复杂度为 O(1),无论阈值容量如何。
555

被折叠的 条评论
为什么被折叠?



