Hystrix Fallback method execution

Dharmvir Tiwari picture Dharmvir Tiwari · Aug 31, 2017 · Viewed 13.7k times · Source

Below is my Hystrix command configuration:

@HystrixCommand(fallbackMethod = "fall", commandProperties = {
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "5"),
            @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000") })
    public <T> T getInfo(Class clazz) {....}

Fallback method:

public <T> T fall(Class clazz) {
        System.out.println("fallback");
        throw new CustomRuntimeException("API Down"); 
    }

I understand that as per the below configuration i.e.

@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "5"),
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000") }

5 request would be allowed in 10s until the circuit trips open and every request from 5th request would be rejected and as i am throwing an exception in the fallback method it would be wrapped as HystrixRuntimeException.

But i am facing below issue:

  • Until the circuit trips open the fallback is executing normally and throwing CustomRuntimeException (Note: Hystrix Command method also throws CustomRuntimeException )
  • After the circuit trips open i getting Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: getInfo short-circuited and fallback failed.

Question:

  1. Why the exception is not wrapped as HystrixRuntimeException before the circuit is open i.e. Currently the fallback is executed normally and throws CustomRuntimeException until the circuit gets open?*

How Hystrix works

  1. Why in flow 1->2->3->4->5->6->8 the fallback method is executed even after failing (i.e. Throwing CustomRuntimeException) and does not throws a wrapped HystrixRuntimeException, which is happening in the case of flow 1->2->3->4->8 and 1->2->3->5->8

Answer

ahus1 picture ahus1 · Sep 2, 2017

Please see the Hystrix Javanica documentation for the exception handling: https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica#error-propagation

Quoting from the docs:

"It is worth noting that by default a caller will always get the root cause exception ... never HystrixBadRequestException or HystrixRuntimeException"

"If command has a fallback then only first exception that triggers fallback logic will be propagated to caller."

These two quotes answer your first question: the exception from the first method will be the exception thrown, not the HystrixRuntimeException. The exception thrown in the fallback will never be shown.

When the circuit breaker is open, a RuntimeException will be thrown. Again, the exception thrown in the fallback will never be shown.

I wrote a test case for this: https://github.com/ahus1/hystrix-spring-examples/blob/master/src/test/java/de/ahus1/hystrixspring/HystrixExceptionHandlingInSpring.java

Side notes:

  1. you added the configuration for your cicruit breaker to the code. They are usually better placed in the spring configuration with their full name: hystrix.command.default.circuitBreaker.requestVolumeThreshold.

  2. The requestVolumeThreshold works a bit differently from what you described: it defines the minimum number of requests that are necessary in a time window before the cicruit breaker is allowed to trigger. The errorThresholdPercentage is the percentage of errors that are allowed once the minimum number of requests (5 in your case) has been reached. In your case 5 out of 5 calls failed, that is 100%. 100% is greater than 50% (default value for the circuit breaker), therefore it opens.