1. 程式人生 > 其它 >SpringBoot如何整合spring-retry來實現介面請求重試

SpringBoot如何整合spring-retry來實現介面請求重試

一、重試機制

由於網路不穩定或網路抖動經常會造成介面請求失敗的情況,當我們再去嘗試就成功了,這就是重試機制。

其主要目的就是要儘可能地提高請求成功的概率,但一般情況下,我們請求第一次失敗,程式碼執行就丟擲異常結束了,如果想再次請求可能還需要手工操作,這非常地不方便,可行性也不佳。因此,Spring框架提供了對重試機制支援,並且在Spring Cloud中可以與Hystrix結合使用,可以避免訪問到已經不正常的例項。

二、重試機制要素

重試機制要素如下:

  • 限制重試次數
  • 每次重試的時間間隔
  • 最終失敗結果的報警或事物回滾
  • 在特定失敗異常事件情況下選擇重試

三、重試機制注意事項

對於非冪等性的方法我們要慎用重試機制,可能會造成意料之外的後果。
所謂冪等性:

就是使用者對於同一操作發起的一次請求或者多次請求的結果是一致的,不會因為多次點選而產生了副作用。

四、SpringBoot整合spring-retry

下面我們就來看下,我們應該如何使用SpringBoot來整合spring-retry元件實現重試機制。

1)新增依賴

首先我們在SpringBoot專案中的pom.xml新增相關依賴,如下:

<!-- 重試相關依賴包 -->
<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>

2)新增@EnableRetry註解

在主啟動類Application上新增@EnableRetry註解,實現對重試機制的支援

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

注意:@EnableRetry也可以使用在配置類、ServiceImpl類、方法上

3)新增@Retryable註解

我們針對需要實現重試的方法上新增@Retryable註解,使該方法可以實現重試,這裡我列出ServiceImpl中的一個方法:

@Service
public class RetryServiceImpl implements RetryService {
 
    @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000,multiplier = 1.5))
    public String testRetry() throws Exception {
 
        System.out.println("開始執行程式碼:"+ LocalTime.now());
        int code = 0;
        // 模擬一直失敗
        if(code == 0){
           // 這裡可以使自定義異常,@Retryable中value需與其一致
            throw new Exception("程式碼執行異常");
        }
        System.out.println("程式碼執行成功");
        return "success";
    }
}

說明:@Retryable配置元資料情況:
value :針對指定丟擲的異常型別,進行重試,這裡指定的是Exception
maxAttempts :配置最大重試次數,這裡配置為3次(包含第一次和最後一次)
delay: 第一次重試延遲間隔,這裡配置的是2s
multiplier :每次重試時間間隔是前一次幾倍,這裡是1.5倍

4)Controller測試程式碼

@RestController
@RequestMapping("/test")
public class TestController {
    @Autowired
    private RetryService retryService;
 
    @GetMapping("/retry")
    public String testRetry() throws Exception {
        return retryService.testRetry();
    }
}

5)傳送請求

傳送請求後,我們發現後臺列印情況,確實重試了3次,並且在最後一次重試失敗的情況下,才丟擲異常,具體如下(可以注意下時間間隔):

6)補充:@Recover

一般情況下,我們重試最大設定的次數後,仍然失敗丟擲異常,我們會通過全域性異常處理類進行統一處理,但是我們其實也可以自行處理,可以通過@Recover註解來實現,具體如下:

@Service
public class RetryServiceImpl implements RetryService {
 
    @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000,multiplier = 1.5))
    public String testRetry() throws Exception {
 
        System.out.println("開始執行程式碼:"+ LocalTime.now());
        int code = 0;
        if(code == 0){
            // 這裡可以使自定義異常,@Retryable中value需與其一致
            throw new Exception("程式碼執行異常");
        }
        System.out.println("程式碼執行成功");
        return "success";
    }
 
    /**
     * 最終重試失敗處理
     * @param e
     * @return
     */
    @Recover
    public String recover(Exception e){
 
        System.out.println("程式碼執行重試後依舊失敗");
        return "fail";
    }
}

注意:
1)@Recover的方法中的引數異常型別需要與重試方法中一致
2)該方法的返回值型別與重試方法保持一致
再次測試如下(發現不會再丟擲異常):

本文首發於Java潘老師個人部落格:SpringBoot整合spring-retry元件實現重試機制