嗨,我正在使用spring RestTemplate
调用REST API。API可能很慢,甚至离线。我的应用程序通过一个接一个地发送数千个请求来构建缓存。响应也可能非常慢,因为它们包含大量数据。
我已经将Timeout设置为120秒。我现在的问题是,API可以离线,我得到一个org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
异常。
在API离线的情况下,应用程序应该等待并再次尝试,直到API再次在线。
我可以在没有构建异常循环的情况下在RestTemplate
开箱外实现这一点吗?
谢谢!
我有同样的情况,做了一些谷歌找到了解决方案。给出答案,希望能帮助到别人。您可以设置最大尝试次数和每次尝试的时间间隔。
@Bean
public RetryTemplate retryTemplate() {
int maxAttempt = Integer.parseInt(env.getProperty("maxAttempt"));
int retryTimeInterval = Integer.parseInt(env.getProperty("retryTimeInterval"));
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(maxAttempt);
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
backOffPolicy.setBackOffPeriod(retryTimeInterval); // 1.5 seconds
RetryTemplate template = new RetryTemplate();
template.setRetryPolicy(retryPolicy);
template.setBackOffPolicy(backOffPolicy);
return template;
}
我要执行的rest服务如下。
retryTemplate.execute(context -> {
System.out.println("inside retry method");
ResponseEntity<?> requestData = RestTemplateProvider.getInstance().postAsNewRequest(bundle, ServiceResponse.class, serivceURL,
CommonUtils.getHeader("APP_Name"));
_LOGGER.info("Response ..."+ requestData);
throw new IllegalStateException("Something went wrong");
});
您还可以使用Spring Retry来处理这个注释驱动的问题。这样可以避免实现模板。
添加到您的pom.xml
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.2.RELEASE</version>
</dependency>
为您的应用程序/配置启用它
@SpringBootApplication
@EnableRetry
public class MyApplication {
//...
}
用@Retryable
保护有失效危险的方法
@Service
public class MyService {
@Retryable(maxAttempts=5, value = RuntimeException.class,
backoff = @Backoff(delay = 15000, multiplier = 2))
public List<String> doDangerousOperationWithExternalResource() {
// ...
}
}
Use Spring Retry project (https://dzone.com/articles/spring-retry-ways-integrate, https://github.com/spring-projects/spring-retry).
它是用来解决你的问题的
这个方法拯救了我的一天!!适应力拯救了我的一天。(弹性重试)[1]
RetryConfig config = RetryConfig.custom()
.maxAttempts(4)
.waitDuration(Duration.ofMillis(2000))
.failAfterMaxAttempts(true)
.build();
RetryRegistry registry = RetryRegistry.of(config);
HttpEntity<String> request =
new HttpEntity<>(body, headers);
Retry retry = registry.retry("notification-endpoint-"+System.currentTimeMillis());
AtomicReference<Integer> retries = new AtomicReference<>(0);
retry.getEventPublisher().onRetry(e -> {
log.info("Retrying here!!!. Count: {}", retries.updateAndGet(v -> v + 1));
}).onError(e->{
log.error("Failed to get to client.");
});
if(requestPojo.getMethod().equalsIgnoreCase("GET")) {
response = Retry.decorateCheckedSupplier(
retry,
() -> restTemplateConfig.restTemplate()
.exchange(url, HttpMethod.GET, request, String.class)).unchecked().get();
}
else if(requestPojo.getMethod().equalsIgnoreCase("POST")) {
response = Retry.decorateCheckedSupplier(
retry,
() -> restTemplateConfig.restTemplate()
.exchange(url, HttpMethod.POST, request, String.class)).unchecked().get();
}```
[1]: https://resilience4j.readme.io/docs/retry