Spring異常重試機制 - Spring Retry

目錄

一 . 引入依賴

二 . 在啓用類或業務類上添加@EnableRetry註解啓用重試機制(在啓用類上添加全局有效 , 在業務類上添加僅當前有效)

三 . 使用@Retryable實現重試

四 . 使用@Recover執行補償方法

五 . 測試及結果

六 . 常用屬性說明

七 . 常見問題


在業務場景中 , 有時候會遇到異常後需要重複嘗試的操作 , 例如調用三方接口 , 發送郵件/短信 , 推送消息等等 . 
Spring 提供了Retry組件 , 很方便的解決了上述問題

項目源代碼 : https://download.csdn.net/download/xingbaozhen1210/11384277

一 . 引入依賴

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

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>

二 . 在啓用類或業務類上添加@EnableRetry註解啓用重試機制(在啓用類上添加全局有效 , 在業務類上添加僅當前有效)

package cn.xing.demo.retry;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;

@SpringBootApplication
@EnableRetry//啓用重試機制
public class RetryApplication {

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

三 . 使用@Retryable實現重試

    /** @Retryable() = @Retryable(maxAttempts = 3) , 出現任意異常後再重試2次 */
    @Retryable()
    public void work1() {
        System.out.println("執行方法1 : " + LocalDateTime.now());
        throw new RuntimeException();//模擬異常
    }

    /** 出現指定異常時(RuntimeException) , 再重試3次 , 每次延遲5s , 之後每次延遲翻倍*/
    @Retryable(include = {RuntimeException.class}, maxAttempts = 4, backoff = @Backoff(delay = 2000L, multiplier = 2))
    public void work2() {
        System.out.println("執行方法2 : " + LocalDateTime.now());
        throw new RuntimeException();//模擬異常
    }

四 . 使用@Recover執行補償方法

即使重試之後 , 仍然因爲各種原因導致失敗 , 這時候就可以在補償方法中記錄異常或採用其他措施

    /** 出現指定異常時(NullPointerException) */
    @Retryable(include = NullPointerException.class)
    public void work3() {
        System.out.println("執行方法3 : " + LocalDateTime.now());
        throw new NullPointerException();//模擬異常
    }

    /** 當重試次數達到限定時 , 會執行@Recover註解的補償方法 , 只有在入參與發生異常匹配時纔會執行該補償方法 */
    @Recover
    public void recover(NullPointerException e) {
        System.out.println("執行補償方法 : " + LocalDateTime.now());
    }

五 . 測試及結果

package cn.xing.demo.retry;

import cn.xing.demo.retry.service.WorkService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class RetryTest {

    @Autowired
    private WorkService workService;

    @Test
    public void test1() {
        workService.work1();
    }

    @Test
    public void test2() {
        workService.work2();
    }

    @Test
    public void test3() {
        workService.work3();
    }
}

六 . 常用屬性說明

@Retryable
    value : 指定發生的異常進行重試 
    include : 同value , 默認"" , 當exclude也爲空時 , 所有異常都重試 
    exclude : 排除不重試的異常 , 默認"" , 當include也爲空時 , 所有異常都重試
    maxAttemps : 嘗試次數 , 默認3 . 注意該值包含第一次正常執行的次數 , 即失敗之後重新嘗試2次 , 一共執行3次
    backoff : 重試補償機制 , 默認無 , 屬性配置如下

@Backoff
    delay : 延遲指定時間後(單位毫秒)重試
    multiplier : 指定延遲的倍數 , 每次執行間隔加倍延遲 . 如delay=5000L,multiplier=2 , 第一次重 試爲5S後 , 第二次爲第一次的10S後 , 第三次爲第二次的20S後

七 . 常見問題

1 . maxAttemps 參數爲嘗試次數 , 而非重試次數 . 即=3時 , 會重試2次 , =4時會重試3次 , 因爲它包括了首次正常執行的計數
2 . retry利用了Spring AOP的原理 , 所以底層採用了代理的技術 , 所有同一個方法內調用會使代理失效
    public void work1(){
        work2();
    }
    @Retryable()//work2方法不會執行重試
    public void work2(){
        //...
    }
3 . 有關非冪等的操作(如新增,修改等) , 不要使用重試 , 會影響數據一致性

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章