Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure specific breaker for route with Resilience4j in Spring cloud gateway

I attempt to configure Resilience4j in my spring cloud gateway without success. All that I find is for Hystrix or with pure java.

I have configured the gateway to transfer request on my service, that is ok.

But impossible to configure resilience4j on it. I have a good artifact in reactive for R4J.

Configuration of Resilience4j is different in spring cloud API and gateway?

See my configuration file.

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: helloworld_service
          uri: "https://localhost:8080"
          predicates:
            - Path=/helloworld/**
          filters:
            - RewritePath=/helloworld/(?<segment>.*), /$\{segment}
            - name: CircuitBreaker
              args:
                name: helloworld
      httpclient:
        ssl:
          useInsecureTrustManager: true

# RESILIENCE4J PROPERTIES
resilience4j:
  circuitbreaker:
    configs:
      default:
        #registerHealthIndicator: true
        ringBufferSizeInClosedState: 10
        ringBufferSizeInHalfOpenState: 3
        automaticTransitionFromOpenToHalfOpenEnabled: true
        waitDurationInOpenStateMillis: 2000
        failureRateThreshold: 50
        eventConsumerBufferSize: 10
    instances:
      helloworld:
        baseConfig: default
        ringBufferSizeInClosedState: 5

My dependencies:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
        </dependency>

And the error generated:

reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IllegalArgumentException: Unable to find GatewayFilterFactory with name CircuitBreaker
Caused by: java.lang.IllegalArgumentException: Unable to find GatewayFilterFactory with name CircuitBreaker

Thanks a lot for helping.

like image 737
Jeremy Caillié Avatar asked Sep 16 '25 07:09

Jeremy Caillié


2 Answers

If you want to use external configuration for Resiulience4j circuit breaker , you need to add the following dependencies:

<dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-gateway</artifactId>
       </dependency>
       <dependency>
           <groupId>io.github.resilience4j</groupId>
           <artifactId>resilience4j-spring-boot2</artifactId>
           <version>1.1.0</version>
       </dependency>
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-actuator</artifactId>
       </dependency>

Then in your spring gateway application , inject the loaded Circuitbreaker registery with ur external configuration in spring cloud factory :

    @Bean
    public ReactiveResilience4JCircuitBreakerFactory reactiveResilience4JCircuitBreakerFactory(CircuitBreakerRegistry circuitBreakerRegistry) {
        ReactiveResilience4JCircuitBreakerFactory reactiveResilience4JCircuitBreakerFactory = new ReactiveResilience4JCircuitBreakerFactory();
        reactiveResilience4JCircuitBreakerFactory.configureCircuitBreakerRegistry(circuitBreakerRegistry);
        return reactiveResilience4JCircuitBreakerFactory;
    }

Then add it your external circuit breaker configuration in the applciation yml file for exmaple:

resilience4j.circuitbreaker:
  configs:
    default:
      slidingWindowSize: 10
      minimumNumberOfCalls: 5
      permittedNumberOfCallsInHalfOpenState: 3
      automaticTransitionFromOpenToHalfOpenEnabled: true
      waitDurationInOpenState: 2s
      failureRateThreshold: 50
      eventConsumerBufferSize: 10
      recordExceptions:
        - org.springframework.web.client.HttpServerErrorException
        - java.io.IOException
      ignoreExceptions:
        - java.lang.IllegalStateException
    shared:
      slidingWindowSize: 100
      permittedNumberOfCallsInHalfOpenState: 30
      waitDurationInOpenState: 1s
      failureRateThreshold: 50
      eventConsumerBufferSize: 10
      ignoreExceptions:
        - java.lang.IllegalStateException
  instances:
    backendA:
      baseConfig: default

enable circuit breaker filter in your route with the configured circuit breaker name , example:

spring:
  application:
    name: gateway-service
  output.ansi.enabled: ALWAYS
  cloud:
    gateway:
      routes:
        - id: test-service-withResilient4j
          uri: http://localhost:8091
          predicates:
            - Path=/testService/**
          filters:
            - CircuitBreaker=backendA
            - RewritePath=/testService/(?<path>.*), /$\{path}

and it should be protected now with ur external configured circuit breaker , other wise you can just configure it through code config approach with customizer

like image 82
Mahmoud Romeh Avatar answered Sep 19 '25 14:09

Mahmoud Romeh


There is a problem in current spring-cloud-gateway Hoxton.RELEASE autoconfiguration. You can workaround it with following configuration.

@Configuration
public class Resilience4JConfiguration {

    @Bean
    public FallbackHeadersGatewayFilterFactory fallbackHeadersGatewayFilterFactory() {
        return new FallbackHeadersGatewayFilterFactory();
    }

    @Bean
    public SpringCloudCircuitBreakerFilterFactory resilience4JCircuitBreakerFactory(
            ReactiveResilience4JCircuitBreakerFactory reactiveCircuitBreakerFactory,
            ObjectProvider<DispatcherHandler> dispatcherHandlers) {
        return new SpringCloudCircuitBreakerResilience4JFilterFactory(reactiveCircuitBreakerFactory, dispatcherHandlers);
    }

}
like image 42
bilak Avatar answered Sep 19 '25 15:09

bilak