java Spring RestTemplate:指数退避重试策略

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31906419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 19:20:31  来源:igfitidea点击:

Spring RestTemplate: Exponential Backoff retry policy

javaspringspring-bootgoogle-cloud-messagingresttemplate

提问by Simon

I'm reading up on GCM: https://developers.google.com/cloud-messaging/server

我正在阅读 GCM:https: //developers.google.com/cloud-messaging/server

and one of the requirements is that the server needs to be able to:

其中一项要求是服务器需要能够:

  • handle requests and resend them using exponential back-off.
  • 处理请求并使用指数退避重新发送它们。

I use Spring RestTemplate for my backend which comes from Spring Boot. There doesn't seem to be a method which I can use to set my retry policy in the docs: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html

我使用 Spring RestTemplate 作为我的后端,它来自 Spring Boot。似乎没有一种方法可以用来在文档中设置我的重试策略:http: //docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/ RestTemplate.html

Also when I googled, I found the RetryTemplate, but it is part of Spring Batch and doesn't extend RestTemplate which makes me think that it is not supposed to be used for Rest operations, but rather Spring Batch operations like processing large amount of transactions: http://docs.spring.io/spring-batch/2.1.x/apidocs/org/springframework/batch/retry/support/RetryTemplate.html

另外,当我用谷歌搜索时,我找到了 RetryTemplate,但它是 Spring Batch 的一部分并且没有扩展 RestTemplate 这让我认为它不应该用于 Rest 操作,而是 Spring Batch 操作,例如处理大量事务:http: //docs.spring.io/spring-batch/2.1.x/apidocs/org/springframework/batch/retry/support/RetryTemplate.html

Is there a way I can use exponential backoff with Spring RestTemplate?

有没有办法可以在 Spring RestTemplate 中使用指数退避?

回答by Konstantin Konyshev

Good day!

再会!

I guess, desired behavior could be achived by implementing custom Sleeperclass.

我想,可以通过实现自定义Sleeper类来实现所需的行为。

Next you need to set this sleeper to BackOffPolicyas follows:

接下来,您需要将这个 sleeper 设置为BackOffPolicy,如下所示:

public class RetryTest {

  public static final Logger LOG = LoggerFactory.getLogger(RetryTemplate.class);

  @org.junit.Test
  public void testRT() {
    RetryTemplate retryTemplate = new RetryTemplate();
    final SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
    retryPolicy.setMaxAttempts(5);
    retryTemplate.setRetryPolicy(retryPolicy);

    Sleeper sleeper = new Sleeper() {
      private long timeToSleep = 0;
      @Override
      public void sleep(long timeout) throws InterruptedException {
        if (timeToSleep ==0) {
          timeToSleep = timeout;
        } else {
          timeToSleep = (long) (timeToSleep * Math.E);
        }
        LOG.warn("sleeping for: {}", timeToSleep);
        Thread.sleep(timeToSleep);
      }
    };
    FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy().withSleeper(sleeper);
    retryTemplate.setBackOffPolicy(backOffPolicy);
    retryTemplate.execute(new RetryCallback<Void, ResourceAccessException>() {
      @Override
      public Void doWithRetry(RetryContext retryContext) throws ResourceAccessException {
        LOG.debug(">RetryCount: {}", retryContext.getRetryCount());
        new RestTemplate().getForObject("https://unreachable.host", String.class);
        return null;
      }
    });
  }
}

Also there is ExponentialBackOffPolicyby spring-retry.

spring-retry还有ExponentialBackOffPolicy

Hope this would help.

希望这会有所帮助。

回答by Vikesh Royal

You can use like the below code .

您可以像下面的代码一样使用。

@Retryable(exceptionExpression="#{@exceptionChecker.shouldRetry(#root)}",
  maxAttemptsExpression = "#{@integerFiveBean}",
  backoff = @Backoff(delayExpression = "#{1}", 
    maxDelayExpression = "#{5}", multiplierExpression = "#{1.1}"))
public void service3() {
  ...
}