【问题标题】:Retry java RestTemplate HTTP request if host offline如果主机离线,重试 java RestTemplate HTTP 请求
【发布时间】:2015-11-27 22:07:56
【问题描述】:

您好,我正在使用 spring RestTemplate 来调用 REST API。 API 可能非常缓慢甚至离线。我的应用程序通过一个接一个地发送数千个请求来构建缓存。响应也可能很慢,因为它们包含大量数据。

我已经将超时时间增加到 120 秒。我现在的问题是 API 可以脱机并且我得到一个 org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool 异常。

如果API离线,应用程序应该等待并重试,直到API再次在线。

我可以在RestTemplate 中开箱即用地实现这一点,而无需自己构建异常循环吗?

谢谢!

【问题讨论】:

  • 不,你不能,你必须手动做。此外,如果 120 秒的时间不足以获取数据,则必须联系 API 开发人员。

标签: java spring apache-httpclient-4.x resttemplate


【解决方案1】:

我有同样的情况,并做了一些谷歌搜索找到了解决方案。给出答案,希望对其他人有所帮助。您可以为每次尝试设置最大尝试和时间间隔。

@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;
  }

下面是我要执行的休息服务。

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");
        });

【讨论】:

【解决方案2】:

你也可以使用 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() {
     // ...
  }

}

【讨论】:

    【解决方案3】:

    使用 Spring Retry 项目(https://dzone.com/articles/spring-retry-ways-integratehttps://github.com/spring-projects/spring-retry)。

    它旨在解决像您这样的问题。

    【讨论】:

      【解决方案4】:

      这种方法挽救了我的一天。!!!弹性挽救了我的一天。[恢复力重试][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
      

      【讨论】: