我已经实现了一个Java方法,通过Resttemplate调用外部服务。此外,我还在该方法中实现了一些额外的业务逻辑。如何为这些Rest调用实现重试机制。还需要考虑以下几点:
- 我不能对整个方法进行重试。
- 最好为Rest调用(通过resttemplate)添加重试。
- 应该有一种方式可以禁用不需要的Rest调用的重试选项。
我已经实现了一个Java方法,通过Resttemplate调用外部服务。此外,我还在该方法中实现了一些额外的业务逻辑。如何为这些Rest调用实现重试机制。还需要考虑以下几点:
Spring提供了使用@Retry注解的重试机制。你需要使用以下依赖项。
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.5.RELEASE</version>
</dependency>
Spring提供以下注解。
Spring重试注解
@EnableRetry - 用于在Spring Boot项目中启用Spring Retry
@Retryable - 表示任何方法都可以作为重试候选方法
@Recover - 指定回退方法
我提供以下示例代码。
@Configuration
@EnableRetry
@SpringBootApplication
public class MyApplication {
}
您可以参考完整示例以了解更多信息。
spring-boot-starter-batch
,以获取与spring-boot版本对齐的依赖项。 - Philippe Simo您可以在 HttpClient
中添加重试机制,并将其用于 RestTemplate
,就像这样:
@Bean
public ClientHttpRequestFactory clientFactory() {
HttpClient httpClient = HttpClients.custom()
.setRetryHandler((exception, executionCount, context) -> {
if (executionCount > 3) {
log.warn("Maximum retries {} reached", 3);
return false;
}
if (<some condition for retry>) {
log.warn("Retry {}", executionCount);
return true;
}
return false;
})
.build();
return new HttpComponentsClientHttpRequestFactory(httpClient);
}
@Bean
public RestTemplate customRestTemplate(@Qualifier("clientFactory") ClientHttpRequestFactory clientFactory){
return new RestTemplate(clientFactory);
}
对于 REST API 调用,您可以在客户端级别上实现重试机制,其中实际的 REST 调用正在进行。
@Retryable(value = Exception.class, maxAttemptsExpression = "${retry.maxAttempts}", backoff = @Backoff(delayExpression = "${retry.maxDelay}"))
public Optional<T> getApiCall(String url, String token, Class<T> resClass) {
ResponseEntity<T> response = null;
try {
logger.info(url);
// create headers
HttpHeaders headers = new HttpHeaders();
// set `accept` header
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setBearerAuth(token);
// set custom header
// headers.set("x-request-src", "desktop");
// build the request
HttpEntity<String> entity = new HttpEntity<>("", headers);
// use exchange method for HTTP call
try {
response = this.restTemplate.exchange(url, HttpMethod.GET, entity, resClass, 1);
} catch (HttpStatusCodeException e) {
return errorService.throwException(HttpStatus.NOT_FOUND, EKDError.LIFPRO406);
}
if (response.getStatusCode() == HttpStatus.OK) {
return Optional.ofNullable(response.getBody());
} else {
return errorService.throwException(HttpStatus.NOT_FOUND, EKDError.LIFPRO406);
}
} catch (HttpClientErrorException | HttpServerErrorException e) {
logger.error("Exception in api call : ", e);
return errorService.throwException(HttpStatus.INTERNAL_SERVER_ERROR, EKDError.LIFPRO407);
}
}
现在最大尝试次数和延迟是可配置的,设置应用程序属性maxAttemptsExpression = "${retry.maxAttempts}",backoff = @Backoff(delayExpression = "${retry.maxDelay}"