重试的概念
重试,我们都不陌生,是为了保障逻辑容错性和可用性的一种机制。一般在网络通信组件底层比较常见,比如网络连接操作,如果有网络中断时,一般需要重试几次。
在上层的业务代码里,如果我们需要对某个特定操作加入重试机制,可以硬编码,然后循环调用,累计调用次数,然后设定退出条件。
当有比较多的重试代码浑在正常的业务代码时,会看起来比较混乱,从功能的角度来看,重试的部分可以独立出来,保证常规业务代码的简洁。这正是Spring retry的做法。
开启 Spring Retry
今天介绍下Spring Retry,一种简单无侵入的重试组件。
Spring Retry原来是属于Spring Batch中的一个功能模块,后来独立拆分出来,成一个单独的功能模块。
开启retry
@Configuration
@EnableRetry
public
class
AppConfig { ... }
在业务代码中声明需要retry的方法
用起来很简单,就一个注解。对业务逻辑无侵入。
@Retryable 加在方法上,表示该方法要执行重试的具体逻辑代码,注解里声明的value 中的SqlException表示触发重试的条件,也可以认为是重试策略,maxAttempts是重试次数;backoff中的delay为重试间隔时间,单位为ms;默认的设置为重试3次,间隔1s。
@Recover作为重试最终失败的兜底策略,在重试方法最终抛出某特定异常时被执行。
第一个参数SqlException是作为触发兜底策略的条件,后面的参数是上边重试方法的参数,如有多个的话,顺序须一致,方法返回值也要一致。
实现逻辑
关于@Retryable和@Recover的实现方式,无疑是通过Spring aop来实现,相信了解Spring aop的同学都大概明白,spring处理注解的一贯作法:代理加advice.
搜索@Retryable的usage,可以看到一个MethodInceptor的实现类 AnnotationAwareRetryOperationsInterceptor, 这个类用方法拦截器的形式封装了重试的逻辑。
而 RetryConfiguration 负责把切面逻辑绑定到目标pointcut。
编程式的使用方式
此外,除了上面声明式的使用方式,也可以使用采用编程式的方式直接控制重试过程。
RetryTemplate作为重试的核心类,组织了重试策略RetryPolicy、延后策略BackoffPolicy、RetryListener等重试逻辑中的功能
RetryTemplate是RetryPerations的接口实现,主要体现在以下几个行为:
没错,这几个方法都代表了对目标方法(我们需要重试的方法)的执行,其中参数RetryCallback接口封装了我们的目标方法。
RetryPolicy,决定了如何触发重试
上边列出的是已经就绪的几种具体实现,功能可以从名称一目了然,不再一一阐述
BackOffPolicy决定了重试间隔的具体实现方式,有如下实现
有固定时间的,指数级增加的还有线程sleep等,不再深究各种实现的细节。
Spring Retry使用简单,但功能强大,除了上述基本功能外,甚至可以做熔断机制, 列位看官如有兴趣可去翻看 CircuitBreakerRetryPolicy 源码。
更详细的使用教程不再作说明,大家可以上网搜索。
附上Spring retry的github 地址
https://github.com/spring-projects/spring-retry
SpringAutowired
一个有用的公众号
长按,识别二维码,加关注
原文 https://mp.weixin.qq.com/s/FrdSgvIy-gtxMIfPJlamrA