一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術(shù)|正則表達(dá)式|

服務(wù)器之家 - 編程語言 - JAVA教程 - SpringBoot @Retryable注解方式

SpringBoot @Retryable注解方式

2020-09-18 14:08wtopps JAVA教程

這篇文章主要介紹了SpringBoot @Retryable注解方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

背景

在調(diào)用第三方接口或者使用MQ時,會出現(xiàn)網(wǎng)絡(luò)抖動,連接超時等網(wǎng)絡(luò)異常,所以需要重試。為了使處理更加健壯并且不太容易出現(xiàn)故障,后續(xù)的嘗試操作,有時候會幫助失敗的操作最后執(zhí)行成功。一般情況下,需要我們自行實現(xiàn)重試機(jī)制,一般是在業(yè)務(wù)代碼中加入一層循環(huán),如果失敗后,再嘗試重試,但是這樣實現(xiàn)并不優(yōu)雅。在SpringBoot中,已經(jīng)實現(xiàn)了相關(guān)的能力,通過@Retryable注解可以實現(xiàn)我們想要的結(jié)果。

@Retryable

首先來看一下Spring官方文檔的解釋:

SpringBoot @Retryable注解方式

@Retryable注解可以注解于方法上,來實現(xiàn)方法的重試機(jī)制。

POM依賴

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.retry</groupId>
 <artifactId>spring-retry</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

使用實例

SpringBoot retry的機(jī)制比較簡單,只需要兩個注解即可實現(xiàn)。

啟動類

@SpringBootApplication
@EnableRetry
public class Application {
 public static void main(String[] args) {
  SpringApplication.run(Application.class, args);
 }
}

在啟動類上,需要加入@EnableRetry注解,來開啟重試機(jī)制。

Service類

前面提到過,@Retryable是基于方法級別的,因此在Service中,需要在你希望重試的方法上,增加重試注解。

@Service
@Slf4j
public class DoRetryService {

 @Retryable(value = Exception.class, maxAttempts = 4, backoff = @Backoff(delay = 2000L, multiplier = 1.5))
 public boolean doRetry(boolean isRetry) throws Exception {
  log.info("開始通知下游系統(tǒng)");
  log.info("通知下游系統(tǒng)");
  if (isRetry) {
   throw new RuntimeException("通知下游系統(tǒng)異常");
  }
  return true;
 }
}

來簡單解釋一下注解中幾個參數(shù)的含義:

名稱 含義
interceptor Retry interceptor bean name to be applied for retryable method.
value Exception types that are retryable. Synonym for includes(). Defaults to empty (and if excludes is also empty all exceptions are retried).
include Exception types that are retryable. Defaults to empty (and if excludes is also empty all exceptions are retried).
exclude Exception types that are not retryable. Defaults to empty (and if includes is also empty all exceptions are retried).
label A unique label for statistics reporting. If not provided the caller may choose to ignore it, or provide a default.
stateful Flag to say that the retry is stateful: i.e. exceptions are re-thrown, but the retry policy is applied with the same policy to subsequent invocations with the same arguments. If false then retryable exceptions are not re-thrown.
maxAttempts the maximum number of attempts (including the first failure), defaults to 3
maxAttemptsExpression an expression evaluated to the maximum number of attempts (including the first failure), defaults to 3
backoff Specify the backoff properties for retrying this operation. The default is a simple specification with no properties.
exceptionExpression Specify an expression to be evaluated after the SimpleRetryPolicy.canRetry() returns true - can be used to conditionally suppress the retry.
listeners Bean names of retry listeners to use instead of default ones defined in Spring context.

上面是@Retryable的參數(shù)列表,參數(shù)較多,這里就選擇幾個主要的來說明一下:

interceptor:可以通過該參數(shù),指定方法攔截器的bean名稱

value:拋出指定異常才會重試

include:和value一樣,默認(rèn)為空,當(dāng)exclude也為空時,默認(rèn)所以異常

exclude:指定不處理的異常

maxAttempts:最大重試次數(shù),默認(rèn)3次

backoff:重試等待策略,默認(rèn)使用@Backoff,@Backoff的value默認(rèn)為1000L,我們設(shè)置為2000L;multiplier(指定延遲倍數(shù))默認(rèn)為0,表示固定暫停1秒后進(jìn)行重試,如果把multiplier設(shè)置為1.5,則第一次重試為2秒,第二次為3秒,第三次為4.5秒。

我們把上面的例子執(zhí)行一下,來看看效果:

2019-12-25 11:38:02.492 INFO 25664 --- [   main] c.f.l.service.impl.DoRetryServiceImpl : 開始通知下游系統(tǒng)
2019-12-25 11:38:02.493 INFO 25664 --- [   main] c.f.l.service.impl.DoRetryServiceImpl : 通知下游系統(tǒng)
2019-12-25 11:38:04.494 INFO 25664 --- [   main] c.f.l.service.impl.DoRetryServiceImpl : 開始通知下游系統(tǒng)
2019-12-25 11:38:04.495 INFO 25664 --- [   main] c.f.l.service.impl.DoRetryServiceImpl : 通知下游系統(tǒng)
2019-12-25 11:38:07.496 INFO 25664 --- [   main] c.f.l.service.impl.DoRetryServiceImpl : 開始通知下游系統(tǒng)
2019-12-25 11:38:07.496 INFO 25664 --- [   main] c.f.l.service.impl.DoRetryServiceImpl : 通知下游系統(tǒng)
2019-12-25 11:38:11.997 INFO 25664 --- [   main] c.f.l.service.impl.DoRetryServiceImpl : 開始通知下游系統(tǒng)
2019-12-25 11:38:11.997 INFO 25664 --- [   main] c.f.l.service.impl.DoRetryServiceImpl : 通知下游系統(tǒng)

java.lang.RuntimeException: 通知下游系統(tǒng)異常
...
...
...

可以看到,三次之后拋出了RuntimeException的異常。

@Recover

當(dāng)重試耗盡時,RetryOperations可以將控制傳遞給另一個回調(diào),即RecoveryCallback。Spring-Retry還提供了@Recover注解,用于@Retryable重試失敗后處理方法,此方法里的異常一定要是@Retryable方法里拋出的異常,否則不會調(diào)用這個方法。

@Recover

public boolean doRecover(Throwable e, boolean isRetry) throws ArithmeticException {
 log.info("全部重試失敗,執(zhí)行doRecover");
 return false;
}

對于@Recover注解的方法,需要特別注意的是:

1、方法的返回值必須與@Retryable方法一致

2、方法的第一個參數(shù),必須是Throwable類型的,建議是與@Retryable配置的異常一致,其他的參數(shù),需要與@Retryable方法的參數(shù)一致

/**
 * Annotation for a method invocation that is a recovery handler. A suitable recovery
 * handler has a first parameter of type Throwable (or a subtype of Throwable) and a
 * return value of the same type as the <code>@Retryable</code> method to recover from.
 * The Throwable first argument is optional (but a method without it will only be called
 * if no others match). Subsequent arguments are populated from the argument list of the
 * failed method in order.
 */

@Recover不生效的問題

在測試過程中,發(fā)現(xiàn)@Recover無法生效,執(zhí)行時拋出異常信息:

org.springframework.retry.ExhaustedRetryException: Cannot locate recovery method; nested exception is java.lang.ArithmeticException: / by zero

at org.springframework.retry.annotation.RecoverAnnotationRecoveryHandler.recover(RecoverAnnotationRecoveryHandler.java:61)
at org.springframework.retry.interceptor.RetryOperationsInterceptor$ItemRecovererCallback.recover(RetryOperationsInterceptor.java:141)
at org.springframework.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:512)
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:351)
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:180)
at org.springframework.retry.interceptor.RetryOperationsInterceptor.invoke(RetryOperationsInterceptor.java:115)
at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy157.doRetry(Unknown Source)

追蹤一下異常的信息,進(jìn)入到RecoverAnnotationRecoveryHandler中,找到報錯的方法public T recover(Object[] args, Throwable cause),看一下其實現(xiàn):

SpringBoot @Retryable注解方式

發(fā)現(xiàn)報錯處,是因為method為空而導(dǎo)致的,明明我已經(jīng)在需要執(zhí)行的方法上注解了@Recover,為什么還會找不到方法呢?很奇怪,再來深入追蹤一下:

SpringBoot @Retryable注解方式

打斷點到這,發(fā)現(xiàn)methods列表是空的,那么methods列表是什么時候初始化的呢?繼續(xù)追蹤:

SpringBoot @Retryable注解方式

發(fā)現(xiàn)了初始化methods列表的地方,這里會掃描注解了@Recover注解的方法,將其加入到methds列表中,那么為什么沒有掃描到我們注解了的方法呢?

SpringBoot @Retryable注解方式

很奇怪,為什么明明注解了@Recover,這里卻沒有掃描到呢?

我有點懷疑Spring掃描的部分,可能有什么問題了,回頭去看看@EnableRetry是怎么說的:

SpringBoot @Retryable注解方式

終于找到問題的所在了,對于@EnableRetry中的proxyTargetClass參數(shù),是控制是否對使用接口實現(xiàn)的bean開啟代理類,默認(rèn)的情況下,是不開啟的,問題原因就是這個,我們來實驗一下,把這個參數(shù)改成true:

@EnableRetry(proxyTargetClass = true)

再次運行,果然沒有問題了。

由此得出結(jié)論,當(dāng)使用接口實現(xiàn)的bean時,需要將EnableRetry的參數(shù)改為true,非接口的實現(xiàn),可以使用默認(rèn)配置,即false。

結(jié)語

本篇主要簡單介紹了Springboot中的Retryable的使用,主要的適用場景為在調(diào)用第三方接口或者使用MQ時。由于會出現(xiàn)網(wǎng)絡(luò)抖動,連接超時等網(wǎng)絡(luò)異常。

以上這篇SpringBoot @Retryable注解方式就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/wtopps/article/details/103698635

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产精品视频久久 | 草久久网 | 国产精品成人va在线观看 | 亚洲欧美日韩特级毛片 | 99这里精品 | 好妈妈7在线观看高清 | 国产真实伦对白在线播放 | 国产日韩欧美视频 | 九9热这里真品 | 精品一成人岛国片在线观看 | 无码骚夜夜精品 | 白发在线视频播放观看免费 | 成人福利网站含羞草 | sxx免费看观看美女 sss亚洲国产欧美一区二区 | 日韩欧美高清一区 | 欧美日韩国产亚洲一区二区三区 | 欧美国产视频 | 日产欧产va1 | 2020精品极品国产色在线观看 | 国产欧美日韩视频在线观看一区二区 | 精品91 | 236zz宅宅最新伦理 | 国产免费精彩视频 | 亚洲国产成人在线 | 手机看片自拍自自拍日韩免费 | 视频一区二区三区欧美日韩 | 国产精品国产精品国产三级普 | 天堂在线中文无弹窗全文阅读 | 成人影院视频 | 亚洲国产精品综合欧美 | 成人在线观看视频免费 | 成人精品网 | 四虎网站入口 | 久久亚洲精品AV成人无码 | 亚洲国产精品日韩高清秒播 | 亚洲大爷操| avtt手机版 | 喜爱夜蒲2三级做爰 | 爱色成人网 | 91制片厂 果冻传媒 天美传媒 | 国产高清在线精品一区 |