While attempting to integrate Resilience4J with Spring Cloud Gateway, some features such as retry appear to be working properly, but the Circuit Breaker did not open the state although failure was counted as shown at below screenshot.
@Bean
public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() {
return factory->factory.configureDefault(id->new Resilience4JConfigBuilder(id)
.circuitBreakerConfig(CircuitBreakerConfig.custom()
.slidingWindowSize(5)
.failureRateThreshold(2)
.permittedNumberOfCallsInHalfOpenState(5)
.slowCallDurationThreshold(Duration.ofMillis(200))
.slowCallRateThreshold(50.0F)
.waitDurationInOpenState(Duration.ofSeconds(30))
.slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED)
.build())
.timeLimiterConfig(TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(3000))
.cancelRunningFuture(true)
.build())
.build());
}
and this is route configuration
private Buildable<Route> setPredicateSpec(ApiRoute apiRoute, PredicateSpec predicateSpec) {
BooleanSpec booleanSpec=predicateSpec.path(apiRoute.getPath());
booleanSpec.filters(f->
{
f.circuitBreaker(c->{
c.setName("DDDDDDTTTTT");
c.addStatusCode("500");
});
f.fallbackHeaders(config ->{
config.setExecutionExceptionMessageHeaderName("message-header");
config.setExecutionExceptionTypeHeaderName("type-header");
config.setRootCauseExceptionMessageHeaderName("root-cause-message-header");
config.setRootCauseExceptionTypeHeaderName("root-cause-type-header");
});
f.filter(authenticationFilter);
f.retry(config->{
config.setMethods(HttpMethod.GET);
config.setRetries(2);
config.setBackoff(Duration.ofMillis(50),Duration.ofMillis(500),0,false);
config.setStatuses(HttpStatus.INTERNAL_SERVER_ERROR);
});
f.requestRateLimiter(r->{
r.setKeyResolver(apiKeyResolver);
r.setRateLimiter(rateLimiter);
});
return f;
});
if (!StringUtils.isEmpty(apiRoute.getMethod())) {
booleanSpec.and()
.method(apiRoute.getMethod());
}
return booleanSpec.uri(apiRoute.getUri());
}
and
As a result, failures have been counted, but the failure rate is -1
Here are my properties as well.
spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key=false
management.endpoint.gateway.enabled=true
management.endpoint.health.show-details=always
management.health.circuitbreakers.enabled=true
management.endpoints.web.exposure.include=health
management.endpoint.metrics.enabled=true
management.endpoints.web.exposure.include=*
management.endpoint.prometheus.enabled= true
management.metrics.export.prometheus.enabled= true
spring.cloud.circuitbreaker.resilience4j.enabled = true
as well as my dependencies
implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc'
implementation 'org.springframework.boot:spring-boot-starter-data-redis-reactive'
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.6.11'
implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'javax.xml.bind:jaxb-api:2.3.1'
implementation 'org.mapstruct:mapstruct:1.5.2.Final'
annotationProcessor 'org.projectlombok:lombok'
runtimeOnly "io.opentelemetry.javaagent:opentelemetry-javaagent:1.18.0"
runtimeOnly 'io.micrometer:micrometer-core'
runtimeOnly 'io.micrometer:micrometer-registry-prometheus'