Search code examples
spring-webfluxproject-reactorcircuit-breakerresilience4j

resilience4J + Spring Boot 2.x


I am using resilience4j for fault tolerance in reative API spring boot application. I can see that all events are treated as success even though Mono is returning errors.

service layer

    @Override
    @CircuitBreaker(name = "member-service")
    public Mono<String> getMemberInfo(String memberId) {
        return wsClient.getMemberInfo(memberId); 
       // This call will return WSException whenever there is 4XX or 5XX error
    }

application.yml configuration

resilience4j.circuitbreaker:
  backends:
    member-service:
      ringBufferSizeInClosedState: 1
      ringBufferSizeInHalfOpenState: 2
      waitInterval: 10000
      failureRateThreshold: 75
      registerHealthIndicator: true
      recordExceptions:
        - com.xx.WSException
      ignoreExceptions:
        - com.xxx.WSClientException

I intentionally changed URI path, so that WebClient always return 404 error, which throws WSException. When I see below endpoint, type is always SUCCESS. Did I miss something?

http://localhost:8088/circuitbreaker-events/member-service

{
"circuitBreakerEvents": [
{
"circuitBreakerName": "member-service",
"type": "SUCCESS",
"creationTime": "2019-02-18T21:56:21.588+05:30[Asia/Calcutta]",
"durationInMs": 6
},
{
"circuitBreakerName": "member-service",
"type": "SUCCESS",
"creationTime": "2019-02-18T21:56:21.588+05:30[Asia/Calcutta]",
"durationInMs": 5
},
{
"circuitBreakerName": "member-service",
"type": "SUCCESS",
"creationTime": "2019-02-18T21:56:21.588+05:30[Asia/Calcutta]",
"durationInMs": 6
}
}

Solution

  • Your method always returns Mono. Even if there is an error. And @CircuitBreaker annotation reacts on exception (not error Mono).

    So you should apply CircuitBreakerOperator to your reactive code.

    public class MemberService {
        private final WsClient wsClient;
        private final CircuitBreaker circuitBreaker;
    
        public MemberService(WsClient wsClient,
                             CircuitBreakerRegistry circuitBreakerRegistry,
                             CircuitBreakerProperties circuitBreakerProperties) {
            this.wsClient = wsClient;
            this.circuitBreaker = circuitBreakerRegistry.circuitBreaker(
                    "member-service",
                    () -> circuitBreakerProperties
                            .createCircuitBreakerConfig("member-service"));
        }
    
        public Mono<String> getMemberInfo(String memberId) {
            return wsClient.getMemberInfo(memberId)
                    .transform(CircuitBreakerOperator.of(circuitBreaker));
        }
    }
    

    You need resilience4j-reactor and resilience4j-spring-boot2 dependencies.