1. 程式人生 > >spring-retry重試支援

spring-retry重試支援

什麼時候需要重處理?

在實際工作中,重處理是一個非常常見的場景,比如:傳送訊息失敗,呼叫遠端服務失敗,爭搶鎖失敗,等等,這些錯誤可能是因為網路波動造成的,等待過後重處理就能成功.通常來說,會用try/catch,while迴圈之類的語法來進行重處理,但是這樣的做法缺乏統一性,並且不是很方便,要多寫很多程式碼.然而spring-retry卻可以通過註解,在不入侵原有業務邏輯程式碼的方式下,優雅的實現重處理功能.

思路

使用@Retryable和@Recover實現重處理,以及重處理失後的回撥

1.pom引用

<dependency>
 <groupId>org.springframework.retry</groupId
>
<artifactId>spring-retry</artifactId> </dependency>

2.應用啟動類開啟retry

@EnableRetry
public class BaseApplication {
  .......
}

3.在指定方法上標記@Retryable來開啟重試

@Retryable(value={A異常.class,B異常.class},
      maxAttempts=重試次數,
      backoff = @Backoff(value = 每次重試延遲毫秒數))
public Integer retry
() { LOGGER.info("測試retry"); final int a = 5; int num = new SecureRandom().nextInt(); if (num % a == 0) { return num; } throw new RetryException("重試失敗"); }

4.在指定方法上標記@Recover來開啟重試失敗後呼叫的方法(注意,需跟重處理方法在同一個類中)

@Recover
public void recover(A異常 e) {
 // ... do something
}

@Recover
public void recover(B異常 e) {
 // ...
do something }

@EnableRetry能否重試。當proxyTargetClass屬性為true時,使用CGLIB代理。預設使用標準JAVA註解。在spring Boot中此引數寫在程式入口即可。
@Retryable 標註此註解的方法在發生異常時會進行重試
value:指定處理的異常類

        include:指定處理的異常類和value一樣,預設為空,當exclude也為空時,預設所有異常

        exclude:指定異常不處理,預設空,當include也為空時,預設所有異常

        maxAttempts:最大重試次數。預設3次

        backoff: 重試等待策略。預設使用@Backoff註解

@Backoff 重試等待策略
delay:指定延遲後重試
multiplier:指定延遲的倍數,比如delay=5000l,multiplier=2時,第一次重試為5秒後,第二次為10秒,第三次為20秒

       不設定引數時,預設使用FixedBackOffPolicy(指定等待時間),重試等待1000ms
       設定delay,使用FixedBackOffPolicy(指定等待時間),重試等待填寫的時間
       設定delay和maxDealy時,重試等待在這兩個值之間均態分佈
       設定delay、maxDealy、multiplier,使用 ExponentialBackOffPolicy(指數級重試間隔的實現 ),multiplier即指定延遲倍數,比如delay=5000l,multiplier=2,則第一次重試為5秒,第二次為10秒,第三次為20秒……

@Recover 用於@Retryable重試失敗後處理方法,此註解註釋的方法引數一定要是@Retryable丟擲的異常,否則無法識別,可以在該方法中進行日誌處理。

例子:

    @Retryable(value= {BusinessException.class},maxAttempts = 3,backoff = @Backoff(delay = 5000l,multiplier = 2))  
    public void call() throws Exception {  
        logger.info("do something...");  
        throw new BusinessException("RPC呼叫異常");  
    }  
    @Recover  
    public void recover(BusinessException e) {  
        logger.info(" ---------------------------  ");  
        logger.info(e.getMessage());  
    }