Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Feign client retry on exception

So far we have a feign client which in case of exception, we used to retry as below

Retryer<ClientResponse> retryer = RetryerBuilder.<ClientResponse>newBuilder()
  .retryIfExceptionOfType(FeignException.class)
  .withStopStrategy(StopStrategies.stopAfterAttempt(retryCount))
  .withWaitStrategy(WaitStrategies.exponentialWait(maxWaitSeconds, TimeUnit.SECONDS))
  .build();
    
retryer.call(() -> { 
  return client.doStuffs(someInput); }
);

recently I tried moving from this custom retryer to an inbuilt feign retryer as below :

Feign client = Feign.builder()
    .decoder(jacksonDecoder)
    .encoder(jacksonEncoder)
    .logger(slf4jLogger)
    .client(okHttpClient)
    .retryer(new Retryer.Default(
                            SECONDS.toMillis(minWaitSeconds), 
                            SECONDS.toMillis(maxWaitSeconds), 
                            retryCount
            ))
    .requestInterceptor(new BasicAuthRequestInterceptor(clientConfig.getUser(), clientConfig.getPassword()))
    .target(target);
    
client.doStuffs(someInput);

understanding was that feign client itself would be taking care of exception but apparently, that's not the case, the minute client throws a 5xx, I get an exception with no retries. Is there something else needed for the implementation to retry?

this service is in dropwizard, git and SO threads are mostly around spring / ribbon which is not the case with me.

dep

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-core</artifactId>
    <version>${feign.version}</version>
</dependency>
like image 221
NoobEditor Avatar asked Jul 11 '19 10:07

NoobEditor


People also ask

Does feign retry by default?

Default Implementation. Feign provides a sensible default implementation of the Retryer interface. It'll retry only a given number of times, will start with some time interval, and then increase it with each retry up to provided maximum.

How do you get feign client exception?

We had same use case to handle exceptions based on error code and we used custom ErrorDecoder . Return @Bean of above class in FeignClientConfiguration class. Use this as your config class for FeignClient. Then you can handle these exceptions using GlobalExceptionHandler .

What is RetryableException?

Class RetryableExceptionThis exception is raised when the Response is deemed to be retryable, typically via an ErrorDecoder when the status is 503.

How feign client works internally?

A central concept in Spring Cloud's Feign support is that of the named client. Each feign client is part of an ensemble of components that work together to contact a remote server on demand, and the ensemble has a name that you give it as an application developer using the @FeignClient annotation.


1 Answers

Without additional configuration, Feign will retry on IOExceptions only. If you wish to retry based on status codes, you will need to create an ErrorDecoder that throws a RetryableException or derivative of, in order to trigger a retry.

Here is simple example:

class MyErrorDecoder implements ErrorDecoder {
    public Exception decode(String methodKey, Response response) {
        if (response.status() == 503) {
            throw new RetryableException(
                response.status(), 
                "Service Unavailable", 
                response.request().httpMethod(), 
                null);
        } else {
            return new RuntimeException("error");
        }
    }
}

For more examples, take a look at the Error Handling documentation.

like image 153
Kevin Davis Avatar answered Oct 05 '22 22:10

Kevin Davis