How to say Hystrix not to trigger fallback for some of the exceptions in Hystrix command

Viewed 16736

We were using the Hystrix functionality by directly extending the HystrixCommand class. But for some of the business exceptions, Hystrix's fallback method is being triggered.

I don't want to trigger the Hystrix fallback for some of the business specific exceptions. How I can achieve it without annotation based?

3 Answers

If you wrap your logic in a try/catch and re-throw any exceptions in a HystrixBadRequestException then it will not trigger the fallback.

@Override
protected Object run() throws Exception {
    try {
        return //call goes here
    }
    catch (Throwable e) {
        //We wrap any exceptions in a HystrixBadRequestException because this way any other errors will not
        //trip the short circuit
        throw new HystrixBadRequestException("Exception thrown hystrix call", e);
    }
}

From the docs: http://netflix.github.io/Hystrix/javadoc/com/netflix/hystrix/exception/HystrixBadRequestException.html

An exception representing an error with provided arguments or state rather than an execution failure. Unlike all other exceptions thrown by a HystrixCommand this will not trigger fallback, not count against failure metrics and thus not trigger the circuit breaker.

NOTE: This should only be used when an error is due to user input such as IllegalArgumentException otherwise it defeats the purpose of fault-tolerance and fallback behavior.

Two ways to do this.

  1. Using HystrixCommand annotation and specifying the exception types.

    @HystrixCommand(ignoreExceptions = { HttpStatusCodeException.class, JsonMappingException.class })
    
  2. Using "HystrixBadRequestException" and customize your code in way to just ignore few exception cases or status codes. This implementation will check for specific error codes on exceptions expected with you backend API contract and does not invoke hystrix fallback. Throwing "HystrixBadRequestException" will not count as hystrix fault.

    @HystrixCommand(commandKey = "MyHystrixCommand", fallbackMethod = "myHystrixFallback", threadPoolKey = "ThreadPoolKey")
    public ResponseEntity<String> getServiceCallResponse(String serviceUrl, HttpEntity<?> entity) {
    ResponseEntity<String> resp = null;
    try {
    resp = restTemplate.exchange(serviceUrl, HttpMethod.POST, entity, String.class)
            .getBody();
    }
    catch(Exception e) {
        handleExceptionForHystrix("getServiceCallResponse", e);
    }
    return resp;
    }
    
    private void handleExceptionForHystrix(String function, Exception e) {
            if (e instanceof HttpStatusCodeException) {
                HttpStatus httpStatusCode = ((HttpStatusCodeException)e).getStatusCode();
                if(httpStatusCode.equals(HttpStatus.BAD_REQUEST) || httpStatusCode.equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
                    throw new HystrixBadRequestException("Hystrix Bad Request Exception Occurred" + httpStatusCode, e);
                }
                throw new RuntimeException(function, e);
            }
            throw new RuntimeException(function, e);
        }
    
    
    public ResponseEntity<String> myHystrixFallback(String serviceUrl, HttpEntity<?> entity, Throwable hystrixCommandExp) {
            return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    
Related