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