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 throwsCustomRuntimeException
) - After the circuit trips open i getting
Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: getInfo short-circuited and fallback failed.
Question:
- 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?*
- 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 wrappedHystrixRuntimeException
, which is happening in the case of flow 1->2->3->4->8 and 1->2->3->5->8
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:
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
.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.