简体   繁体   中英

Resilience4J Circuit Breaker to kick-in on specific HTTP status code

I am aware we can use recordExceptions() while building CircuitBreakerConfig to register exceptions on which Circuit Breaker should transition to OPEN state.

Code

I am using resilience4j-feign to decorate my CircuitBreaker . Would be really helpful if you can point me to a code example.

Question

How to make the Circuit Breaker kick-in in case of a specific HTTP status code (eg on 503 Service Unavailable ) ?

from the readme ( https://resilience4j.readme.io/docs/circuitbreaker#section-create-and-configure-a-circuitbreaker )

// Create a custom configuration for a CircuitBreaker
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
  .recordExceptions(IOException.class, TimeoutException.class) // add you exceptions here!!!
  .ignoreExceptions(BusinessException.class, OtherBusinessException.class)
  .build();

A list of exceptions that are recorded as a failure and thus increase the failure rate. Any exception matching or inheriting from one of the list counts as a failure, unless explicitly ignored via ignoreExceptions.

You need to write an Exception/Response handler to your client's external calls and throw custom exceptions based on http status received. Then register these exceptions as record exceptions in your circuit breaker config. Following is a small example. The CB will be open only on AbcException. The CB config is resilience4j.circuitbreaker.instances.bookService.record-exceptions=com.sk.example.cb.circuitbreakerr4j.AbcException

 @Service @Slf4j public class BookApiService { RestTemplate restTemplate = new RestTemplate(); @CircuitBreaker(name = "bookService", fallbackMethod = "getBookFallback") public String getBook(){ try { ResponseEntity<String> stringResponseEntity = restTemplate.getForEntity(new URI("http://localhost:8080/book"), String.class); if(null != stringResponseEntity){ if(stringResponseEntity.getStatusCode().is2xxSuccessful()){ return stringResponseEntity.getBody(); } } } catch (URISyntaxException e) { e.printStackTrace(); }catch (HttpServerErrorException e){ log.error("Service unavailable",e); if(e.getMessage().startsWith("503")) { throw new AbcException(); }else{ throw e; } } return ""; }

TL;DR: use a custom exception that communicates HTTP status (eg 503) from HTTP client (eg Feign) to Resilience4J

  1. Feign: implement and configure an ErrorDecoder to throw a custom exception on HTTP status like 503
  2. Resilience4J: record that custom exception using Circuit Breaker config.

Feign

Feign by default throws a FeignException in case of an erroneous HTTP status code. You can get the status code number via method int status() .

To customize your feign-clients error-handling configure a (custom) implementation of ErrorDecoder

If you need more control over handling unexpected responses, Feign instances can register a custom ErrorDecoder via the builder. [..] All responses that result in an HTTP status not in the 2xx range will trigger the ErrorDecoder 's decode method, allowing you to handle the response, wrap the failure into a custom exception or perform any additional processing. If you want to retry the request again, throw a RetryableException . This will invoke the registered Retryer .

Customize Feign error-handling

Implement and configure a custom ErrorDecoder to throw an exception in case of HTTP status 503.

@Component
@Slf4j
public class CustomErrorDecoder implements ErrorDecoder {
    
    @Override
    public Exception decode(String methodKey, Response response) {
        
        switch (response.status()) {
            case 400:
                log.error("Status code {} on methodKey '{}'", response.status(), methodKey);
            case 503:
                return new ServiceUnavailableException("HTTP status 503 when calling " methodKey);
            default:
                return new Exception(response.reason());
        } 
    }
    
}

This will then throw your custom exception ServiceUnavailableException .

Resilienc4J's CircuitBreaker

By default the circuit-breaker reacts on exceptions. It records them and will open the circuit if there are too much in too less time.

You can configure, which Exceptions to record and which to ignore as expected on the business-level.

Trigger CircuitBreaker on specific exceptions

You can configure CiruitBreaker to record that exception . Joke's answer explains how to do that.

See also

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM