詳解如何在SpringBoot中優(yōu)雅地重試調(diào)用第三方API
前言
作為后端程序員,我們的日常工作就是調(diào)用一些第三方服務(wù),將數(shù)據(jù)存入數(shù)據(jù)庫,返回信息給前端。但你不能保證所有的事情一直都很順利。像有些第三方API,偶爾會出現(xiàn)超時。此時,我們要重試幾次,這取決于你的重試策略。
下面舉一個我在日常開發(fā)中多次看到的例子:
public interface OutSource { List<Integer> getResult() throws TimeOutException; } @Service public class OutSourceImpl implements OutSource { static Random random = new Random(); @Override public List<Integer> getResult() { //mock failure if (random.nextInt(2) == 1) throw new TimeOutException(); return List.of(1, 2, 3); } } @Slf4j @Service public class ManuallyRetryService { @Autowired private OutSource outSource; public List<Integer> getOutSourceResult(String data, int retryTimes) { log.info("trigger time:{}", retryTimes); if (retryTimes > 3) { return List.of(); } try { List<Integer> lst = outSource.getResult(); if (!CollectionUtils.isEmpty(lst)) { return lst; } log.error("getOutSourceResult error, data:{}", data); } catch (TimeOutException e) { log.error("getOutSourceResult timeout", e); } // 遞歸調(diào)用 return getOutSourceResult(data, retryTimes + 1); } } @Slf4j @RestController public class RetryTestController { @Autowired private ManuallyRetryService manuallyRetryService; @GetMapping("manually") public String manuallyRetry() { List<Integer> result = manuallyRetryService.getOutSourceResult("haha", 0); if (!CollectionUtils.isEmpty(result)) { return "ok"; } return "fail"; } }
看看上面這段代碼,我認為它可以正常工作,當(dāng)retryTimes
達到4時,無論如何我們都會得到最終結(jié)果。但是你覺得寫的好嗎?優(yōu)雅嗎?下面我來介紹Spring中的一個組件:spring-retry
,我們不妨來試一試。
Spring-Retry介紹使用
spring-retry
是Spring中的提供的一個重試框架,提供了注解的方式,在不入侵原有業(yè)務(wù)邏輯代碼的方式下,優(yōu)雅的實現(xiàn)重處理功能。
安裝依賴
如果你的是gradle應(yīng)用,引入下面的依賴
implementation 'org.springframework.boot:spring-boot-starter-aop''org.springframework.boot:spring-boot-starter-aop' implementation 'org.springframework.retry:spring-retry'
如果你的項目使用的是maven項目,引入下面的依賴
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
啟用重試功能
添加@EnableRetry
注解在入口的類上從而啟用功能。
@SpringBootApplication //看過來 @EnableRetry public class TestSpringApplication { public static void main(String[] args) { SpringApplication.run(TestSpringApplication.class, args); } }
應(yīng)用
我們以前面的為例,看看怎么使用,如下面的代碼:
public interface OutSource { List<Integer> getResult() throws TimeOutException; } @Service public class OutSourceImpl implements OutSource { static Random random = new Random(); @Override public List<Integer> getResult() { //mock failure will throw an exception every time throw new TimeOutException(); } } @Slf4j @Service public class RetryableService { @Autowired private OutSource outSource; // 看這里 @Retryable(value = {TimeOutException.class}, maxAttempts = 3) public List<Integer> getOutSourceResult(String data) { log.info("trigger timestamp:{}", System.currentTimeMillis() / 1000); List<Integer> lst = outSource.getResult(); if (!CollectionUtils.isEmpty(lst)) { return lst; } log.error("getOutSourceResult error, data:{}", data); return null; } } @Slf4j @RestController public class RetryTestController { @Autowired private RetryableService retryableService; @GetMapping("retryable") public String manuallyRetry2() { try { List<Integer> result = retryableService.getOutSourceResult("aaaa"); if (!CollectionUtils.isEmpty(result)) { return "ok"; } } catch (Exception e) { log.error("retryable final exception", e); } return "fail"; } }
關(guān)鍵在于Service
層中的實現(xiàn)類中添加了 @Retryable
注解,實現(xiàn)了重試, 指定value是TimeOutException
異常會進行重試,最大重試maxAttempts
3次。
驗證
這一次,當(dāng)我們訪問http://localhost:8080/retryable時,我們將看到瀏覽器上的結(jié)果失敗。然后在你的終端上看到:
INFO 66776 --- [nio-9997-exec-1] c.m.testspring.service.RetryableService : trigger timestamp:1668236840
INFO 66776 --- [nio-9997-exec-1] c.m.testspring.service.RetryableService : trigger timestamp:1668236841
INFO 66776 --- [nio-9997-exec-1] c.m.testspring.service.RetryableService : trigger timestamp:1668236842
ERROR 66776 --- [nio-9997-exec-1] c.m.t.controller.RetryTestController : retryable final exception
總結(jié)
本文分享了spring-retry
重試框架最基礎(chǔ)的使用,可以無侵入業(yè)務(wù)代碼進行重試。關(guān)于spring-retry
更多的使用建議可以自己去官網(wǎng)https://github.com/spring-projects/spring-retry 探索。
到此這篇關(guān)于詳解如何在SpringBoot中優(yōu)雅地重試調(diào)用第三方API的文章就介紹到這了,更多相關(guān)SpringBoot重試調(diào)用第三方API內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot如何配置文件properties和yml
這篇文章主要介紹了SpringBoot如何配置文件properties和yml問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08Collections工具類_動力節(jié)點Java學(xué)院整理
Collections工具類提供了大量針對Collection/Map的操作。這篇文章主要介紹了Collections工具類_動力節(jié)點Java學(xué)院整理,需要的朋友可以參考下2017-04-04Java8使用Stream流實現(xiàn)List列表查詢、統(tǒng)計、排序以及分組
List的Stream流操作可以簡化我們的代碼,減少程序運行的壓力,應(yīng)對上面的問題,下面這篇文章主要給大家介紹了關(guān)于Java8使用Stream流實現(xiàn)List列表查詢、統(tǒng)計、排序以及分組的相關(guān)資料,需要的朋友可以參考下2023-06-06使用IDEA將Java/Kotliin工程導(dǎo)出Jar包的正確姿勢
這篇文章主要介紹了使用IDEA將Java/Kotliin工程導(dǎo)出Jar包的正確姿勢,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03基于HTML5+js+Java實現(xiàn)單文件文件上傳到服務(wù)器功能
應(yīng)公司要求,在HTML5頁面上實現(xiàn)上傳文件到服務(wù)器功能,對于我這樣的菜鳥,真是把我難住了,最后還是請教大神搞定的,下面小編把例子分享到腳本之家平臺,供大家參考2017-08-08