如果主机离线,请重试java RestTemplate HTTP请求



嗨,我正在使用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

最新更新