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元件實現重試機制