Spring 源码篇-Spring Retry

写在前面

Spring Retry为Spring提供的重试模块,spring retry是从spring batch独立出来的一个能功能,主要实现了重试和熔断。对于重试是有场景限制的,不是什么场景都适合重试,比如参数校验不合法、写操作等(要考虑写是否幂等)都不适合重试。远程调用超时、网络突然中断可以重试。在微服务治理框架中,通常都有自己的重试与超时配置,比如dubbo可以设置retries=1,timeout=500调用失败只重试1次,超过500ms调用仍未返回则调用失败。在spring retry中可以指定需要重试的异常类型,并设置每次重试的间隔以及如果重试失败是继续重试还是熔断(停止重试)。目前提供了注解方式使用,包括@EnableRetry,@Retryable,@Backoff等注解。

使用

在启动类中使用@EnableRetry注解。

@SpringBootApplication
@EnableRetry
public class SpringDemoRetryApplication {
   

    public static void main(String[] args) {
   
        SpringApplication.run(SpringDemoRetryApplication.class, args);
    }

}

在需要重试机制中加入重试注解,包括熔断和重试模式。

@Service
@Slf4j
public class HelloServiceImpl implements HelloService {
   
    @Override
    @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 1.5))
    public String hello(String username) {
   
        log.debug("hello,{}",username);
        int random=(int)(Math.random()*30);
        if(random%4!=0){
   
            throw new RuntimeException("error");
        }
        return "hello world,"+username;
    }
}

测试结果如下,重试三次失败,采用最快失败。

6699 [main] DEBUG o.s.retry.support.RetryTemplate - Retry: count=0 
6832 [main] DEBUG c.m.s.d.r.s.impl.HelloServiceImpl - hello,luzhu 
6833 [main] DEBUG o.s.r.b.ExponentialBackOffPolicy - Sleeping for 2000 
8833 [main] DEBUG o.s.retry.support.RetryTemplate - Checking for rethrow: count=1 
8833 [main] DEBUG o.s.retry.support.RetryTemplate - Retry: count=1 
8833 [main] DEBUG c.m.s.d.r.s.impl.HelloServiceImpl - hello,luzhu 
8834 [main] DEBUG o.s.r.b.ExponentialBackOffPolicy - Sleeping for 3000 
11834 [main] DEBUG o.s.retry.support.RetryTemplate - Checking for rethrow: count=2 
11835 [main] DEBUG o.s.retry.support.RetryTemplate - Retry: count=2 
11835 [main] DEBUG c.m.s.d.r.s.impl.HelloServiceImpl - hello,luzhu 
11835 [main] DEBUG o.s.retry.support.RetryTemplate - Checking for rethrow: count=3 
11836 [main] DEBUG o.s.retry.support.RetryTemplate - Retry failed last attempt: count=3 

源码分析

重试模块主要由spring-retry模块实现,代码组织如下:
代码组织

  • 重试接口(RetryOperations)
    RetryOperations类主要实现了对重试的接口,RetryTemplate为其实现。主要包括execute方法,RetryCallback为重试需要执行的操作,RecoverCallback为重试结束后如何返回,比如提供默认值等等,即重试失败后需要进行的操作。重试包括如何重试,RetryTemplate默认的重试策略为SimpleRetryPlicy。
    RetryTemplate类图
  • 重试上下文(RetryContext)
    重试上下文接口为RetryContext,其中继承了AttributeAccessor接口,此接口提供了对扩展属性的增删查改操作,用于对不同重试情况下特性的支持,RetryContext实现由AttributeAccessorSupport类实现(map集合实现)。RetryContextSupport类提供了一些重试基础数据的记录,包括重试次数,重试上文,最新异常,是否结束等。默认实现为SimpleRetryContext。
    • SimpleRetryContext:默认实现;
    • NeverRetryContext:新增是否结束字段;
    • TimeoutRetryContext:扩展开始时间和过期时间字段,判断是否过期;
      重试上下文
  • 重试策略(RetryPolicy)
    重试策略接口为RetryPolicy,其中包括是否能够重试canRetry,打开重试上下文 open,关闭重试上下文close,注册异常信息registerThorwable四个类。具体策略中open将打开对应的上下文,比如NeverRetryPolicy打开NeverRetryContext,而具体是否继续重试由canRetry控制,比如NeverRetry会去判断context是否结束(!((NeverRetryContext) context).isFinished();),AlwaysRetryPolicy策略一直返回true;SimpleRetryPolicy会去
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值