0

I'm using Feign from the spring-cloud-starter-feign to send requests to a defined backend. I would like to use Hystrix as a circuit-breaker but for only one type of use-case: If the backend responds with a HTTP 429: Too many requests code, my Feign client should wait exactly one hour until it contacts the real backend again. Until then, a fallback method should be executed.

How would I have to configure my Spring Boot (1.5.10) application in order to accomplish that? I see many configuration possibilities but only few examples which are - in my opinion - unfortunately not resolved around use-cases.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
user3105453
  • 1,881
  • 5
  • 32
  • 55

2 Answers2

1

This can be achieved by defining an ErrorDecoder and taking manual control of the Hystrix Circuit Breaker. You can inspect the response codes from the exceptions and provide your own fallback. In addition, if you wish to retry the request, wrap and throw your exception in a RetryException.

To meet your Retry requirement, also register a Retryer bean with the appropriate configuration. Keep in mind that using a Retryer will tie up a thread for the duration. The default implementation of Retryer does use an exponential backoff policy as well.

Here is an example ErrorDecoder taken from the OpenFeign documentation:

public class StashErrorDecoder implements ErrorDecoder {

    @Override
    public Exception decode(String methodKey, Response response) {
        if (response.status() >= 400 && response.status() <= 499) {
            return new StashClientException(
                response.status(),
                response.reason()
            );
        }
        if (response.status() >= 500 && response.status() <= 599) {
            return new StashServerException(
                response.status(),
                response.reason()
            );
        }
        return errorStatus(methodKey, response);
    } 
}

In your case, you would react to 419 as desired.

You can forcibly open the Circuit Breaker setting this property at runtime

hystrix.command.HystrixCommandKey.circuitBreaker.forceOpen

ConfigurationManager.getConfigInstance()
    .setProperty(
    "hystrix.command.HystrixCommandKey.circuitBreaker.forceOpen", true);

Replace HystrixCommandKey with your own command. You will need to restore this circuit breaker back to closed after the desired time.

Kevin Davis
  • 1,193
  • 8
  • 14
  • Thank you for your answer, you pointed me in the right direction. I wanted to avoid using the built-in Hystrix client of Feign, as advised by Spencer Gibb: https://stackoverflow.com/questions/39499973/how-to-fine-tune-the-spring-cloud-feign-client/39517091#39517091 – user3105453 Mar 18 '18 at 17:15
0

I could solve it with the following adjustments:

Properties in application.yml:

hystrix.command.commandKey:
  execution.isolation.thread.timeoutInMilliseconds: 10_000
  metrics.rollingStats.timeInMilliseconds: 10_000
  circuitBreaker:
    errorThresholdPercentage: 1
    requestVolumeThreshold: 1
    sleepWindowInMilliseconds: 3_600_000

Code in the respective Java class:

@HystrixCommand(fallbackMethod = "fallbackMethod", commandKey = COMMAND_KEY)
public void doCall(String parameter) {
    try {
        feignClient.doCall(parameter);
    } catch (FeignException e) {
        if (e.status() == 429) {
            throw new TooManyRequestsException(e.getMessage());
        } 
    }
}
user3105453
  • 1,881
  • 5
  • 32
  • 55