Spring RestTemplate:指数退避重试策略

时间:2015-08-09 16:37:55

标签: java spring spring-boot google-cloud-messaging resttemplate

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

并且其中一个要求是服务器需要能够:

  • 处理请求并使用指数后退重新发送它们。

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

当我用Google搜索时,我找到了RetryTemplate,但它是Spring Batch的一部分,并没有扩展RestTemplate,这让我觉得它不应该用于Rest操作,而是像Spring Batch操作那样处理大量交易:http://docs.spring.io/spring-batch/2.1.x/apidocs/org/springframework/batch/retry/support/RetryTemplate.html

有没有办法可以使用Spring RestTemplate进行指数退避?

2 个答案:

答案 0 :(得分:6)

美好的一天!

我想,通过实现自定义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;
      }
    });
  }
}

弹簧重试也有ExponentialBackOffPolicy

希望这会有所帮助。

答案 1 :(得分:1)

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

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