Spring中的retry重試組件詳解
一、簡介
Spring-retry 前面我們了解到了,Guava的重試組件,我們可以基于Guava的能力,來封裝我們需要的能力來滿足我們的業(yè)務(wù)。
今天來分享Spring-Retry重試組件。當然Spring只是幫我們封裝好了,如果你不想自定義 重試組件,那么我們可以直接使用Spring的能力來實現(xiàn)。
API 也是非常的簡單,幾個注解就可以搞定。
二、依賴
<!--springboot項目都不用引入版本號--> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <!--還是需要aop的支持的(如果已經(jīng)引入了aop就不用再添加這個依賴了)--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency>
三、使用
3.1 @EnableRetry 開啟重試
SpringBoot啟動類上添加開啟重試注解
@EnableRetry @SpringBootApplication public class Application { public static void main(String[] args) { ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args); } }
3.2 @Retryable 重試策略
在需要重試的方法上加注解@Retryable
@Retryable(value = RuntimeException.class, maxAttempts = 5, backoff = @Backoff(delay = 100)) public String say(String param) { double random = Math.random(); if (random > 0.1) { throw new RuntimeException("超時"); } return random + ""; }
- value = RuntimeException.class:是指方法拋出RuntimeException異常時,進行重試。這里可以指定你想要攔截的異常。
- maxAttempts:是最大重試次數(shù)。如果不寫,則是默認3次。
- backoff = @Backoff(delay = 100):是指重試間隔。delay=100意味著下一次的重試,要等100毫秒之后才能執(zhí)行。
3.3 @Recover 重試失敗
當@Retryable方法重試失敗之后,最后就會調(diào)用@Recover方法。用于@Retryable失敗時的“兜底”處理方法。 @Recover的方法必須要與@Retryable注解的方法保持一致,第一入?yún)橐卦嚨漠惓?,其他參?shù)與@Retryable保持一致,返回值也要一樣,否則無法執(zhí)行!
@Retryable(value = IllegalAccessException.class) public void say() throws IllegalAccessException { log.info("do something... {}", LocalDateTime.now()); throw new IllegalAccessException(); } @Recover public void sayBackup(IllegalAccessException e) { log.info("service retry after Recover => {}", e.getMessage()); }
3.4 @CircuitBreaker 熔斷策略
規(guī)定時間內(nèi)如果重試次數(shù)達到了最大次數(shù),開啟熔斷策略。 5秒內(nèi),這個方法重試了2次,就會斷路。直接走@Recover修飾的方法。當超過10s后進行重置,繼續(xù)走get方法。
注意@Retryable和@CircuitBreaker不要修飾同一個方法。
@CircuitBreaker(openTimeout = 5000, maxAttempts = 2,resetTimeout = 10000) public String get(@PathVariable Integer flag) { if (flag > 1) { log.info("重試進入"); throw new RuntimeException("自定義異常"); } return "處理正常"; } @Recover public String getBackup(RuntimeException runtimeException) { log.error("重試一直失敗,進入備用方法:" + runtimeException.getMessage()); return "備用方法進去"; }
屬性 | 說明 |
include | 指定處理的異常類。默認為空 |
exclude | 指定不需要處理的異常。默認為空 |
value | 指定要重試的異常。默認為空 |
maxAttempts | 最大重試次數(shù)。默認3次 |
openTimeout | 配置熔斷器打開的超時時間,默認5s,當超過openTimeout之后熔斷器電路變成半打開狀態(tài)(只要有一次重試成功,則閉合電路) |
resetTimeout | 配置熔斷器重新閉合的超時時間,默認20s,超過這個時間斷路器關(guān)閉 |
include | 指定處理的異常類。默認為空 |
3.5 RetryListener 監(jiān)聽器
spring-retry和guava-retry一樣同樣有監(jiān)聽器。我們可以自定義我們的監(jiān)聽器
@Slf4j public class DefaultListenerSupport extends RetryListenerSupport { @Override public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) { log.info("onClose"); super.close(context, callback, throwable); } @Override public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) { log.info("onError"); super.onError(context, callback, throwable); } @Override public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) { log.info("onOpen"); return super.open(context, callback); } } @Configuration public class RetryConfig { @Bean public RetryTemplate retryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); //設(shè)置重試策略 retryPolicy.setMaxAttempts(2); retryTemplate.setRetryPolicy(retryPolicy); FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy(); //設(shè)置退避策略 fixedBackOffPolicy.setBackOffPeriod(2000L); retryTemplate.setBackOffPolicy(fixedBackOffPolicy); retryTemplate.registerListener(new DefaultListenerSupport()); //設(shè)置retryListener return retryTemplate; } }
3.6 RetryPolicy 重試策略
屬性 | 說明 |
NeverRetryPolicy | 只允許調(diào)用RetryCallback一次,不允許重試; |
AlwaysRetryPolicy | 允許無限重試,直到成功,此方式邏輯不當會導(dǎo)致死循環(huán); |
SimpleRetryPolicy | 固定次數(shù)重試策略,默認重試最大次數(shù)為3次,RetryTemplate默認使用的策略; |
TimeoutRetryPolicy | 超時時間重試策略,默認超時時間為1秒,在指定的超時時間內(nèi)允許重試; |
CircuitBreakerRetryPolicy | 有熔斷功能的重試策略,需設(shè)置3個參數(shù)openTimeout、resetTimeout和delegate |
CompositeRetryPolicy | 組合重試策略,有兩種組合方式,樂觀組合重試策略是指只要有一個策略允許重試即可以,悲觀組合重試策略是指只要有一個策略不允許重試即可以,但不管哪種組合方式,組合中的每一個策略都會執(zhí)行。 |
3.7 BackOffPolicy 退避策略
下一次重試的策略。 退避是指怎么去做下一次的重試,在這里其實就是等待多長時間。
屬性 | 說明 |
FixedBackOffPolicy | 默認固定延遲1秒后執(zhí)行下一次重試 |
ExponentialBackOffPolicy | 指數(shù)遞增延遲執(zhí)行重試,默認初始0.1秒,系數(shù)是2,那么下次延遲0.2秒,再下次就是延遲0.4秒,如此類推,最大30秒。 |
ExponentialRandomBackOffPolicy | 在上面那個策略上增加隨機性 |
UniformRandomBackOffPolicy | 這個跟上面的區(qū)別就是,上面的延遲會不停遞增,這個只會在固定的區(qū)間隨機 |
StatelessBackOffPolicy | 這個說明是無狀態(tài)的,所謂無狀態(tài)就是對上次的退避無感知,從它下面的子類也能看出來 |
四、總結(jié)
天下代碼一大抄,看你會抄不會抄。發(fā)現(xiàn)無論是guava還是spring的重試,基本都是類似的思路。只是看誰的功能比較鑒權(quán)而已。 guava提供了基礎(chǔ)的能力,你任意封裝。 spring基于spring提供了已經(jīng)完好的能力,直接使用就好。不過因為是spring給你封裝的能力,所以你要先了解清楚才行。不然可能使用錯誤,造成故障。
以上兩款工具都挺好,不過他們都不支持分布式重試的能力。不過這已經(jīng)滿足我們的日常開發(fā)了,如果真遇到分布式的重試,就自己來實現(xiàn)咯。
到此這篇關(guān)于Spring中的retry重試組件詳解的文章就介紹到這了,更多相關(guān)retry重試組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring?Boot集成LiteFlow規(guī)則引擎的詳細過程
本文詳細介紹了如何在Spring?Boot應(yīng)用程序中集成LiteFlow規(guī)則引擎,并探討如何使用LiteFlow庫來實現(xiàn)業(yè)務(wù)流程的規(guī)則處理,將通過具體的示例來展示如何在Spring?Boot應(yīng)用程序中配置和使用LiteFlow規(guī)則引擎,以提高系統(tǒng)的靈活性和可維護性,感興趣的朋友跟隨小編一起看看吧2024-07-07Java使用Hutool+自定義注解實現(xiàn)數(shù)據(jù)脫敏
我們在使用手機銀行的時候經(jīng)常能看到APP上會將銀行卡的卡號中間部分給隱藏掉使用 ***** 來代替,在某些網(wǎng)站上查看一些業(yè)務(wù)密碼時(例如簽到密碼等)也會使用 ***** 來隱藏掉真正的密碼,那么這種方式是如何實現(xiàn)的呢,本文將給大家介紹使用Hutool+自定義注解實現(xiàn)數(shù)據(jù)脫敏2023-09-09Mybatis-Plus同時使用邏輯刪除和唯一索引的問題及解決辦法(報數(shù)據(jù)重復(fù)Duplicate entry的
在開發(fā)中,我們經(jīng)常會有邏輯刪除和唯一索引同時使用的情況,但當使用mybatis plus時,如果同時使用邏輯刪除和唯一索引,會報數(shù)據(jù)重復(fù)Duplicate entry的問題,如何解決這個問題呢,小編給大家分享Mybatis-Plus同時使用邏輯刪除和唯一索引的問題及解決辦法,一起看看吧2023-11-11Java循環(huán)調(diào)用多個timer實現(xiàn)定時任務(wù)
這篇文章主要介紹了Java循環(huán)調(diào)用多個timer實現(xiàn)定時任務(wù),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07Java多線程之synchronized關(guān)鍵字的使用
這篇文章主要介紹了Java多線程之synchronized關(guān)鍵字的使用,文中有非常詳細的代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04Mybatis-Plus的應(yīng)用場景描述及注入SQL原理分析
MyBatis-Plus是一個 MyBatis 的增強工具,在 MyBatis 的基礎(chǔ)上只做增強不做改變,為簡化開發(fā)、提高效率而生,本文重點給大家介紹Mybatis-Plus的應(yīng)用場景及注入SQL原理分析,感興趣的朋友跟隨小編一起學(xué)習(xí)吧2021-05-05Java String 和StringBuffer的詳解及區(qū)別
這篇文章主要介紹了Java String 和StringBuffer的詳解及區(qū)別的相關(guān)資料,需要的朋友可以參考下2017-05-05