在业务系统中,经常会遇到进行业务重试的场景,当一个执行方法失败时,可能需要进行几次重试,如果重试时成功了,仍然认为业务是正确的。否则则throw相应的异常。这种通用的重试场景则可以使用标准的第三方重试库来完成,以避免自己在业务代码中写类似while try 的代码。同时,因为重试的条件以及处理的逻辑均不太一样,通过一个标准的重试库来完成此操作,也是很有必要的。
本文描述了spring提供的重试库spring-retry,通过提取相应的概念模型,了解其工作原理以及执行机制.
版本:1.2.2.RELEASE
Retryable
用于标识一个可以进行重试的方法,即一个方法如果需要在throw异常之后进行重试,则可以使用此注解进行标记.同时,此注解上标识了可以进行重试的一些条件以及次数信息。
Backoff
此标识一个方法在进行下一次重试时,需要暂停的一些手法以及参数信息,比如sleep多少秒,或者是是在一个区间范围内sleep。
Recover
此标识当一个方法执行多次都失败之后,进行的一个failback处理。
RetryContext
重试上下文,即维护了整个重试周期中相应调用对象,调用次数,以及在调用过程中的异常对象等,其它接口均从此对象中获取相应的数据.
RetryOperations
封装了一个主要可重试操作,可以理解为进行主要逻辑操作的template对象。
RetryPolicy
与@Backoff相对应的一个接口,用于在整个重试逻辑中,处理何时该重试,以及控制相应的重试上下文信息。
RetryListener
监听器,用于在重试过程中,对开始,重试出错,结束时进行拦截操作。默认情况下,此类为null,即无作用。
RetryCallback
简单的重试回调对象,用于封装原来的可重试方法,将整个操作统一使用callback来表示,以隔离相应的实现。
RecoveryCallback
与@Recover相对应,即最终进行failback的回调对象.
整个spring-retry的执行逻辑均封装在RetryTemplate这个类中,然后在外部通过RetryConfiguration来配置一些额外的业务接口信息,最终形成一个bean拦截器,通过拦截bean的调用来完成重试的处理.
一个简单的执行逻辑(以无状态重试为例)
整个逻辑参照于类RetryTemplate#doExecute方法,其中 recoveryCallback对象为null,即无failback. state为null,即不是有状态的重试.
在实际的业务场景当中,对于一个业务方法 doBusiness(), 我们期望对此方法进行重试操作,在调用此方法时,如果throw了一个TimeoutException,则进行重试,重试次数为3,每次重试时间隔1秒。
对于这个业务场景,则相应的配置则如下参考所示:
@Retryable(maxAttempts=3, backoff=@Backoff(1000)) public void doBusiness() { //do your business }
其实spring-retry的整个概念还是很简单的,只不过考虑场景太多,以至于一些源码理解上偏麻烦,但对于整个重试场景来说,spring-retry在模型和接口上的整理还是很值得参考。在一个简单的业务场景中,可以自己发明一个小轮子来完成类似的事务。在一些类似的设计场景,也可以考虑类似的方法和实现.