spring

spring-retry 重試機制

謝騏澤 2019/10/14 10:23:48
133

前言

在實作中,重試處理是一個非常常見的情況,例如:傳送訊息失敗,呼叫遠端服務失敗等等...,這些錯誤可能是因為網路不穩造成的,等待過後,在重試就能成功。通常會用try/catch,while迴圈來進行重試處理的控制,然而spring-retry卻可以使用@annotation來方便的實現重試處理的功能。
 


如何使用spring-retry?

  • pom.xml新增spring-retry
<!-- https://mvnrepository.com/artifact/org.springframework.retry/spring-retry -->
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>1.2.4.RELEASE</version>
</dependency>
  • build.gradle新增spring-retry
// https://mvnrepository.com/artifact/org.springframework.retry/spring-retry
compile group: 'org.springframework.retry', name: 'spring-retry', version: '1.2.4.RELEASE'

 

Application上添加@EnableRetry

@SpringBootApplication
@EnableRetry
public class DemoApplication {

   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }

}

 

在需要重試方法上添加@Retryable

        以下針對常用的值進行介紹

  • value:指定失敗重試的Exception類型
  • include:和value效果一樣,當exclude為空時,所有Exceoption都會重試,預設空
  • exclude:指定Exceoption不重試,當include為空時,所有Exceoption都會重試,預設空
  • maxAttempts:指定重試的次數,預設3
  • backoff:重試補償機制,預設沒有

        @Backoff

             delay:指定延遲後重試

             multiplier:指定延遲的倍数,例如:delay=3000l, multiplier=2,第一次重試為3秒,第二次為6秒,第三次為12秒

@Retryable(value = DemoException.class, maxAttempts = 4, backoff = @Backoff(delay = 3000l))
public void testSpringRetry() {
    logger.info("測試Spring Retry重試---------------------------- {}", LocalTime.now());
    throw new DemoException();
}

 

在重試回調的方法上添加@Recover

重試的次數達到所指定的次數時,就會執行此方法

注意:發生Exception和參數的Exception類型需要一致才會回調

@Recover
private void testRecover(DemoException e){
    logger.error("測試Recover...");
}

 

添加測試spring-retry

@PostMapping(path = "/testSpringRetry")
public String testSpringRetry() {
    demoService.testSpringRetry();
    return "";
}

 

@Retryable執行結果

  • 執行結果可以發現,方法重試了四次,而且每隔三秒重試一次
  • 重試四次後,執行@Recover的方法

 

與re-try-catch做比較

public void testTryCatchRedo() throws Exception {
    int count = 0;
    int maxAttempts = 4;
    int delaySec = 3;
    while (true) {
        try {
            logger.info("測試try-catch-redo重試---------------------------- {}", LocalTime.now());
            throw new DemoException();
        } catch (DemoException e) {
            Thread.sleep(delaySec * 1000);

            if (++count == maxAttempts)
                throw e;
        }
    }
}

 

添加測試re-try-catch

@PostMapping(path = "/testSpringRetry")
public String testSpringRetry() {
    demoService.testSpringRetry();
    return "";
}

 

re-try-catch執行結果

  • 與上面的@Retryable執行結果一樣
  • 方法重試了四次,而且每隔三秒重試一次

 

結語

透過spring-retry就能簡單地透過設定來進行重試機制,而不在需要使用較為繁瑣的寫法來控制重試機制。

 

謝騏澤