在程序的運(yùn)行過程中一定會(huì)出現(xiàn)由于某些原因發(fā)生意外的情況,這種時(shí)候我們可以通過重新執(zhí)行來確保程序能夠執(zhí)行成功,Spring框架中有一個(gè)小組件spring-retry提供了自動(dòng)重試的功能。這在錯(cuò)誤可能是短暫的(例如瞬間的網(wǎng)絡(luò)故障)情況下非常有幫助。如果使用原生的Java寫法,我們?cè)撊绾翁幚碇卦嚨哪?
上面的代碼雖然也可以實(shí)現(xiàn)重試的功能,但是代碼顯得比較臃腫,而且重試的代碼和業(yè)務(wù)代碼耦合在一起,如果以后需要修改重試的次數(shù)或者重試間隔,就需要修改代碼,這樣顯然是不合理的,那么有沒有更好的方式呢?這一次我們介紹使用SpringRetry組件實(shí)現(xiàn)重試功能。
1.引入依賴
在pom文件中添加spring-retry和aop的依賴:
通過spring-retry實(shí)現(xiàn)重試的方式有兩種,一種是聲明式使用注解,另一種是編程式。
2.聲明式
在需要重試的方法上添加@Retryable注解,同時(shí)在配置類上加@EnableRetry注解啟用重試。下面是一個(gè)示例:
啟動(dòng)類
在service中添加方法,方法上添加@Retryable注解,傳遞一個(gè)string類型的參數(shù),當(dāng)參數(shù)為error時(shí)模擬發(fā)生故障拋出異常。
從輸出結(jié)果可以看出,當(dāng)程序發(fā)生異常時(shí),第二次重試間隔為500ms,第三次重試間隔為1000ms,第四次重試間隔為2000ms,第五次重試間隔為4000ms,以此類推。
也可以通過@Recover注解標(biāo)記一個(gè)方法作為兜底方案,當(dāng)重試次數(shù)達(dá)到最大次數(shù)后還是執(zhí)行失敗,會(huì)調(diào)用@Recover注解標(biāo)記的方法。@Recover注解標(biāo)記的方法的返回值類型必須和@Retryable注解標(biāo)記的方法一致,@Recover必須和@Retryable標(biāo)記的方法在同一個(gè)類中。下面是一個(gè)示例:
3.編程式
下面是一個(gè)示例:
在配置類中創(chuàng)建一個(gè)RetryTemplateBean,交給Spring管理。
在service中注入RetryTemplate,調(diào)用execute方法執(zhí)行需要重試的方法。下面是一個(gè)示例:
如果在業(yè)務(wù)邏輯處理的過程中發(fā)生了異常,會(huì)自動(dòng)進(jìn)行重試,在這個(gè)例子中會(huì)重試3次,每次間隔時(shí)間為1秒。如果重試3次后還是發(fā)生異常,會(huì)拋出異常,可以在catch中處理最終異常。
也可以在retryTemplate中添加監(jiān)聽器,監(jiān)聽器會(huì)在重試的過程中提供額外的回調(diào),可以利用這些回調(diào)處理不同重試中的各種情況,下面是一個(gè)示例:
在創(chuàng)建RetryTemplate時(shí)注冊(cè)監(jiān)聽器,監(jiān)聽器重寫之后可以重寫RetryListener接口中的open,close,onError,onSuccess方法,分別對(duì)應(yīng)重試開始,重試結(jié)束,重試發(fā)生異常,重試成功時(shí)調(diào)用。我們這次重寫onError方法,當(dāng)發(fā)生異常時(shí)打印重試次數(shù)。
下面是對(duì)RetryTemplate的簡(jiǎn)單介紹:
FixedBackOffPolicy:每次重試間隔固定時(shí)間。
ExponentialBackOffPolicy:每次重試間隔時(shí)間指數(shù)增長(zhǎng)。
NoBackOffPolicy:不進(jìn)行退避,每次重試間隔時(shí)間為0。
UniformRandomBackOffPolicy:隨機(jī)間隔時(shí)間,每次重試間隔時(shí)間為一個(gè)隨機(jī)數(shù)。
SimpleRetryPolicy:簡(jiǎn)單的重試策略,可以指定重試的最大次數(shù)和捕獲的異常。
CircuitBreakerRetryPolicy:斷路器重試策略,可以防止重試次數(shù)過多導(dǎo)致系統(tǒng)崩潰。
TimeoutRetryPolicy:超時(shí)重試策略,可以防止重試時(shí)間過長(zhǎng)導(dǎo)致系統(tǒng)崩潰。
CompositeRetryPolicy:組合重試策略,可以組合多個(gè)重試策略一起使用。
4.應(yīng)用場(chǎng)景
當(dāng)程序因?yàn)榕紶柕木W(wǎng)絡(luò)抖動(dòng),數(shù)據(jù)庫(kù)鎖的獲取,消息隊(duì)列的消費(fèi)端因?yàn)橘Y源不足,調(diào)用三方應(yīng)用時(shí)因?yàn)閷?duì)方系統(tǒng)繁忙導(dǎo)致請(qǐng)求失敗等原因。
spring-retry提供簡(jiǎn)單易用的重試機(jī)制,可以提高系統(tǒng)的可靠性和健壯性。