Spring Cloud Gateway Circuit Breaker Blocks Load Balanced Route

46 Views Asked by At

Using Spring Cloud Gateway MVC and Spring Boot, I have configured a route to a microservice that has multiple instances which are load balanced using a Eureka discovery service. I then added a circuit breaker filter for resilience. I've elected to use the Java-based config.

I set up two microservices - one that will always succeed and one that will always fail (timeout). The incoming requests are routed to one of those two services using the load balancer (round-robin). Half the requests succeed, and half fail (timeout). The circuit breaker then opens because of the bad service and blocks traffic to both the good and bad service. I figure this is because the circuit breaker opens for the whole route instead of only on the one load balanced service instance.

How would I configure the route so that the circuit breaker blocks only the bad service instance and continues to route all traffic to the good service instance?

  • Spring cloud version 2023.0.0
  • Circuit Breaker is resilience4j (artifactId: spring-cloud-starter-circuitbreaker-resilience4j)
  • Load Balancer is Eureka (artifactId: spring-cloud-starter-netflix-eureka-client)
@Bean
public RouterFunction<ServerResponse> serviceRouteConfig() {
    return RouterFunctions
        .route()
        .route(GatewayRequestPredicates.path("/api/service/**"), HandlerFunctions.http())
        .before(BeforeFilterFunctions.stripPrefix(2)) // remove "/api/service/"
        .filter(LoadBalancerFilterFunctions.lb("SERVICE-NAME"))
        .filter(CircuitBreakerFilterFunctions.circuitBreaker("defaultCircuitBreaker"))
        .build();
}

@Bean
public Customizer<Resilience4JCircuitBreakerFactory> defaultCircuitBreakerCustomizer() {
    return factory -> factory
        .configureDefault(
            id -> new Resilience4JConfigBuilder(id)
                .circuitBreakerConfig(
                    CircuitBreakerConfig.custom()
                    .slidingWindowType(SlidingWindowType.COUNT_BASED)
                    .slidingWindowSize(5)
                    .minimumNumberOfCalls(5)
                    .build())
                .timeLimiterConfig(TimeLimiterConfig.custom()
                    .timeoutDuration(Duration.ofSeconds(2)).build())
                .build());
}
0

There are 0 best solutions below