CircuitBreaker не меняет состояние с HALF_OPEN на CLOSED
У меня есть эта конфигурация автоматического выключателя в моем реактивном приложении с пружинной загрузкой -
CircuitBreakerConfig.custom().failureRateThreshold(5)
.slowCallDurationThreshold(Duration.ofMillis(5000))
.slidingWindowType(SlidingWindowType.COUNT_BASED)
.slidingWindowSize(5)
.permittedNumberOfCallsInHalfOpenState(5)
.waitDurationInOpenState(Duration.ofMillis(30000))
.slowCallRateThreshold(5)
то я вызываю восходящий API вот так -
return Mono.from(invokeUpstream(body, headers))
.compose(CircuitBreakerOperator.of(circuitBreaker)).onErrorResume(this::fallback);
то invokeUpstream метод выглядит следующим образом -
Mono<ResponseEntity<String>> response = webClient.post()
.body(BodyInserters.fromValue(body))
.retrieve()
.onStatus(HttpStatus::is5xxServerError, clientResponse -> Mono.error(new BadGatewayException()))
.toEntity(String.class);
И резервный метод просто генерирует исключение -
private Mono<ResponseEntity<String>> fallback(Throwable ex) {
throw new BadGatewayException();
}
Теперь, когда вышестоящий API возвращает 500 ответов 5 раз, я вижу, что состояние прерывателя цепи переходит в состояние ОТКРЫТО из состояния ЗАКРЫТО, что ожидалось. В ОТКРЫТОМ состоянии он остается в течение 30 секунд согласно конфигурации. После этого он переходит в состояние HALF_OPEN, и проблема начинается здесь. Даже если вышестоящий API возвращает успешный ответ, он никогда не переходит в состояние ЗАКРЫТО, он всегда остается в состоянии HALF_OPEN.
Я использую эти зависимости в своем приложении -
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-circuitbreaker</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-reactor</artifactId>
<version>1.3.1</version>
</dependency>
Я не уверен, что делаю неправильно, даже после просмотра всей документации.
1 ответ
Я нашел проблему. Я проверял состояние выключателя, используя
circuitBreaker.tryAcquirePermission()
еще до совершения фактического вызова, который вызывал эту проблему. После удаления он работает отлично.