??在我們的日常開發(fā)中,經(jīng)查會遇到調用接口失敗的情況,這時候就需要通過一些方法來進行重試,比如通過while循環(huán)手動重復調用或是通過JDK/CGLib動態(tài)代理的方式來進行重試。但是這種方法比較笨重,且對原有邏輯代碼的入侵性比較大仇箱。
??實際上,Spring已經(jīng)為我們提供了封裝好的重試功能东羹,spring-retry剂桥,使我們可以通過@Retryable和@Recover注解來完成重試和重試失敗后的回調。
??如上圖中的代碼所示百姓,我們通過@Retryable注解渊额,對RemoteAccessException異常進行重試,重試次數(shù)為2次,第一次重試間隔為5s旬迹,之后重試的時間間隔為前一次的2倍火惊,第二次重試間隔10s,第三次重試間隔20s奔垦。然后通過@Recover注解設定當重試到達指定次數(shù)時屹耐,將要回調的方法。
我們來看看@Retryable注解中有什么內(nèi)容:
參數(shù) | 含義 |
---|---|
interceptor | 重試攔截器bean名稱椿猎,用于可重試方法 |
value | 可重試的異常類型惶岭。含義同include。 默認為空(如果excludes也為空犯眠,則重試所有異常) |
include | 可重試的異常類型按灶。默認為空(如果excludes也為空,則重試所有異常) |
exclude | 無需重試的異常類型筐咧。默認為空(如果includes也為空鸯旁,則重試所有異常) |
label | 統(tǒng)計報告的唯一標簽。如果未提供量蕊, 則調用者可以選擇忽略它或提供一個默認值铺罢。 我的理解就是這個重試方法的唯一名稱 |
stateful | 若為true,標志重試是有狀態(tài)的:即重新拋出異常残炮, 但是重試策略與相同的策略應用于具有相同參數(shù)的后續(xù)調用韭赘。 若為false,則不會重新引發(fā)可重試的異常 |
maxAttempts | 最大重試次數(shù)(包括第一次失敗)势就,默認為3次 |
maxAttemptsExpression | 計算最大嘗試次數(shù)(包括第一次失敗)的表達式泉瞻,默認為3 次 |
backoff | 重試等待策略,下面會在@Backoff中介紹 |
exceptionExpression | 指定在SimpleRetryPolicy.canRetry()返回true之后要求值的表達式-可用于有條件地禁止重試。 |
另外苞冯,還有@Backoff注解:
參數(shù) | 含義 |
---|---|
value | 這個我不知道瓦灶,原文是"A canonical backoff period." |
delay | 重試之間的等待時間(以毫秒為單位) |
maxDelay | 重試之間的最大等待時間(以毫秒為單位) |
multiplier | 指定延遲的倍數(shù) |
delayExpression | 重試之間的等待時間表達式 |
maxDelayExpression | 重試之間的最大等待時間表達式 |
multiplierExpression | 指定延遲的倍數(shù)表達式 |
random | 隨機指定延遲時間 |
從圖中可以發(fā)現(xiàn),我們可以通過setRetryPolicy()方法來為RetryTemplate設置重試策略刃泡。Spring為我們提供了6種重試策略:
1.NeverRetryPolicy:只允許調用 RetryCallback 一次巧娱,不允許重試
2.AlwaysRetryPolicy:允許無限重試,直到成功烘贴,此方式邏輯不當會導致死循環(huán)
3.SimpleRetryPolicy:固定次數(shù)重試策略禁添,默認重試最大次數(shù)為 3 次,RetryTemplate 默認使用的策略
4.TimeoutRetryPolicy:超時時間重試策略桨踪,默認超時時間為 1 秒老翘,在指定的超時時間內(nèi)允許重試
5.CircuitBreakerRetryPolicy:有熔斷功能的重試策略,需設置 3 個參數(shù) openTimeout、resetTimeout 和 delegate
6.CompositeRetryPolicy:組合重試策略铺峭。有兩種組合方式墓怀,樂觀組合重試策略是指只要有一個策略允許重試即可以,悲觀組合重試策略是指只要有一個策略不允許重試即不可以卫键。但不管哪種組合方式傀履,組合中的每一個策略都會執(zhí)行
在使用@Retryable和@Recover注解時,有幾點需要注意:
首先莉炉,要添加maven依賴
<dependency>
?? <groupId>org.springframework.retry</groupId>
??<artifactId>spring-retry</artifactId>
</dependency>
并添加@EnableRetry注解使@Retryable和@Recover注解生效钓账。
另外@Retryable和@Recover修飾的方法要在同一個類中,且被@Retryable 標記的方法不能有返回值,這樣Recover方法才會生效絮宁。
最后,由于@Retryable注解是通過切面實現(xiàn)的梆暮,因此我們要避免@Retryable 注解的方法的調用方和被調用方處于同一個類中,因為這樣會使@Retryable 注解失效绍昂。