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>
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.
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 .
Class RetryableExceptionThis exception is raised when the Response is deemed to be retryable, typically via an ErrorDecoder when the status is 503.
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.
Without additional configuration, Feign will retry on IOException
s 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With