Spring retry使用和采坑記錄


1. 介紹

在項目中,調用第三方接口響應比較慢,或者由於網絡抖動等原因,導致無響應的情況,就要用到重試機制.比較簡單成熟的方案就是使用spring-retry功能,spring-retry需要使用aop的特性,所以引入aspectj

2. 項目依賴

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

2. 核心注解

核心注解3個: @EnableRetry,@Retryable@Recover

@EnableRetry:此注解用於開啟重試框架,可以修飾在SpringBoot啟動類上面,也可以修飾在需要重試的類上
   proxyTargetClass:Boolean類型,用於指明代理方式【true:cglib代理,false:jdk動態代理】默認使用jdk動態代理
@Retryable
   value:Class[]類型,用於指定需要重試的異常類型,
   include:Class[]類型,作用於value類似,區別尚未分析
   exclude:Class[]類型,指定不需要重試的異常類型
   maxAttemps:int類型,指定最多重試次數,默認3
   backoff:Backoff類型,指明補償機制
   @BackOff
      delay:指定延遲后重試,默認為1000L,即1s后開始重試 ;
      multiplier:指定延遲的倍數
@Recover
   當重試次數耗盡依然出現異常時,執行此異常對應的@Recover方法。
   異常類型需要與Recover方法參數類型保持一致,
   recover方法返回值需要與重試方法返回值保證一致

https://blog.csdn.net/qq_39914581/java/article/details/96506043

3. 使用步驟

springboot開啟重試

@SpringBootApplication
@EnableRetry
public class ReadscoreApplication {

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

}

添加重試注解,當有異常時觸發重試機制.設置重試5次,默認是3.延時2000ms再次執行,每次延時提高1.5倍.當返回結果不符合要求時,主動報錯觸發重試.

@Retryable(value = Exception.class, maxAttempts = 5, backoff = @Backoff(delay = 2000, multiplier = 1.5))
public String download() throws Exception {
    // 模擬測試
    if(StringUtils.isBlank(null)){
        log.info("重試查詢下載鏈接: {}", LocalTime.now());
        throw new Exception("正在導出文件,請稍后");
    }else {
        return result;
    }
}

定義回調,注意異常類型和方法返回值類型要與重試方法一致

@Recover
public String recover(Exception e){
    log.error("獲取下載鏈接失敗! {}", LocalTime.now());
    throw new Exception("獲取下載鏈接失敗!");
}

模擬重試結果

2020-07-22 14:32:57.124 INFO  com.service.PaperService:80 - 重試查詢下載鏈接: 14:32:57.122
2020-07-22 14:32:59.341 INFO  com.service.PaperService:80 - 重試查詢下載鏈接: 14:32:59.341
2020-07-22 14:33:02.560 INFO  com.service.PaperService:80 - 重試查詢下載鏈接: 14:33:02.560
2020-07-22 14:33:07.308 INFO  com.service.PaperService:80 - 重試查詢下載鏈接: 14:33:07.308
2020-07-22 14:33:14.286 INFO  com.service.PaperService:80 - 重試查詢下載鏈接: 14:33:14.286
2020-07-22 14:33:14.286 ERROR com.service.PaperService:89 - 獲取下載鏈接失敗! 14:33:14.286
2020-07-22 14:33:14.287 INFO  com.controller.PaperController:79 - com.exception.ParamsException      : 正在導出文件,請稍后

采坑記錄:

1. retry重試機制無效

由於retry用到了aspect增強,所有會有aspect的坑,就是方法內部調用,會使aspect增強失效,那么retry當然也會失效。

public class demo {
    public void A() {
        B();
    }

    @Retryable(Exception.class)
    public void B() {
        throw new RuntimeException("retry...");
    }
}

這種情況B()不會重試。

2. recover回調報錯

org.springframework.retry.ExhaustedRetryException: Cannot locate recovery method
報錯顯示找不到recovery方法

解決方案就這這兩句話:

  • 異常類型需要與Recover方法參數類型保持一致

  • recover方法返回值需要與重試方法返回值保證一致

異常類型和返回值要一致!

參考:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM