Home > database >  Retry rest calls to external APIs for selected set of Http error status codes
Retry rest calls to external APIs for selected set of Http error status codes

Time:11-16

in order to add retry utility to external API calls, I am thinking of using Spring @Retryable annotation as follows:

@Service
public class MyService {

  @Retryable(maxAttempts=3, value = Exception.class, 
             backoff = @Backoff(delay = 100, multiplier = 2))
  public List<String> doCallExternalResource() {
     // ...
  }

}

I would like to do retries for the following errors:

1. 500 Internal Server Error
2. 502 Bad Gateway
3. 503 Service Unavailable
4. 504 Gateway Timeout

But I am not able to understand, how can I do this with the @Retryable annotation approach.

Could anyone please help here? Thanks.

CodePudding user response:

Retryable annotation is used to call a service method and, if it fails with a specific exception that you specify on @Retryable, it try again according to maxAttempts (by default is 3, in your case too). You can use @Recover annotation to specify what the method should do if method with Retryable annotation fails. More in the documentation.

For example:

@Service
class Coordinate {
    @Retryable(GatewayTimeout.class)
    public void service() {
        // ...main method
    }
    @Recover
    public void recover(GatewayTimeout e) {
       // do something if SQLException occurs 3 times.
    }
}

In your case, you may use GatewayTimeout.class instead of HttpServerErrorException.GATEWAY_TIMEOUT

CodePudding user response:

I think the four kinds of errors you mentioned all have corresponding exceptions:

    @Retryable(maxAttempts=3,
        value = {
            HttpServerErrorException.InternalServerError.class, 
            HttpServerErrorException.BadGateway.class, 
            HttpServerErrorException.ServiceUnavailable.class, 
            HttpServerErrorException.GatewayTimeout.class},
        backoff = @Backoff(delay = 100, multiplier = 2))
    public List<String> doCallExternalResource() {}

CodePudding user response:

You need to write a custom http client to achieve this and call using that custom http cleint. Here is an example

CloseableHttpClient httpClient = HttpClients.custom()
    .setServiceUnavailableRetryStrategy(new ServiceUnavailableRetryStrategy() {
        @Override
        public boolean retryRequest(
                final HttpResponse response, final int executionCount, final HttpContext context) {
            int statusCode = response.getStatusLine().getStatusCode();
            return statusCode == 500 || statusCode == 502 || statusCode == 503 || statusCode == 504; 
        }

        @Override
        public long getRetryInterval() {
            return 0;
        }
    })
    .build();

You should also limit the number of retry otherwise retry will happen infinite times until succeed. You can limit the number of retry on executionCount parameters

  • Related