ITPub博客

首页 > 数据库 > 数据库开发技术 > OpenFeign重试组件Retryer原理

OpenFeign重试组件Retryer原理

原创 数据库开发技术 作者:服务端技术栈 时间:2023-06-25 08:10:00 0 删除 编辑

前言

前面三篇文章已经分析了Feign的通信Client组件,Client是Rpc框架中最核心关键的能力,通过Client发起远程通信。

Feign框架最核心可扩展组件通信Client详解

OpenFeign是怎样集成Ribbon负载均衡能力的?

OpenFeign集成Ribbon负载均衡-过滤和选择服务核心实现

市面上的Rpc框架在核心通信能力的基础上,有很多服务治理的组件,OpenFeign也一样,今天主角是重试组件,我们看看OpenFeign是如何实现重试的。

‍
 重试组件入口
‍

OpenFeign执行远程请求是在feign.SynchronousMethodHandler#invoke,重试组件也是在这里嵌入的,我们看看具体实现

//调用远程入口public Object invoke(Object[] argv) throws Throwable {        RequestTemplate template = this.buildTemplateFromArgs.create(argv);        Request.Options options = this.findOptions(argv);        Retryer retryer = this.retryer.clone();        //死循环,如果成功或者重试结束就返回        while(true) {            try {                //通过client发起通信                return this.executeAndDecode(template, options);            } catch (RetryableException var9) {                //处理RetryableException异常                RetryableException e = var9;                try {                    //重试组件生效,判断是否重试                    retryer.continueOrPropagate(e);                } catch (RetryableException var8) {                    Throwable cause = var8.getCause();                    if (this.propagationPolicy == ExceptionPropagationPolicy.UNWRAP && cause != null) {                        throw cause;                    }
throw var8; } } }}

发起请求的地方捕获了RetryableException异常,并且执行了重试的逻辑。 Feign提供了两个重试实现

1、feign.Retryer.Default

2、feign.Retryer#NEVER_RETRY

OpenFeign默认使用不重试

‍从openfeign的装配类FeignClientsConfiguration我们可以看出 在OpenFeign中,默认使用的是NEVER_RETRY,不重试

@Configurationpublic class FeignClientsConfiguration {    @Bean    @ConditionalOnMissingBean    public Retryer feignRetryer() {        //默认配置不重试        return Retryer.NEVER_RETRY;    }}
Retryer NEVER_RETRY = new Retryer() {
@Override public void continueOrPropagate(RetryableException e) {      //异常往外抛,不重试处理 throw e; }
@Override public Retryer clone() { return this; } };

OpenFeign默认重试组件实现分析


feign.Retryer.Default是OpenFeign实现了重试能力的重试组件,我们看下他源码是如何实现的

public static class Default implements Retryer {        private final int maxAttempts;        private final long period;        private final long maxPeriod;        int attempt;        long sleptForMillis;
public Default() { this(100L, TimeUnit.SECONDS.toMillis(1L), 5); }
public Default(long period, long maxPeriod, int maxAttempts) { this.period = period; this.maxPeriod = maxPeriod; this.maxAttempts = maxAttempts; this.attempt = 1; }
protected long currentTimeMillis() { return System.currentTimeMillis(); }        //重试逻辑 public void continueOrPropagate(RetryableException e) { //已经超过最大重试次数,不重试了,异常往上抛 //attempt默认是1 if (this.attempt++ >= this.maxAttempts) { throw e; } else { long interval; //根据上次重试时间计算间隔时间 if (e.retryAfter() != null) { interval = e.retryAfter().getTime() - this.currentTimeMillis(); //间隔时间是否超过最大重试间隔时间 if (interval > this.maxPeriod) { interval = this.maxPeriod; }
if (interval < 0L) { return; } } else { //获取下次重试间隔时间 interval = this.nextMaxInterval(); }
try { //睡眠重试间隔,再发起重试 Thread.sleep(interval); } catch (InterruptedException var5) { Thread.currentThread().interrupt(); throw e; }
this.sleptForMillis += interval; } }
long nextMaxInterval() { //计算下次重试间隔,按照1.5为底的指数递增 long interval = (long)((double)this.period * Math.pow(1.5, (double)(this.attempt - 1))); return interval > this.maxPeriod ? this.maxPeriod : interval; }
public Retryer clone() { return new Default(this.period, this.maxPeriod, this.maxAttempts); } }

1、默认重试是捕获RetryableException异常,如果是RetryableException异常则执行重试逻辑。

2、默认重试组件支持配置重试间隔和最大重试次数

3、每次重试间隔按照底数是1.5的,指数为重试次数级递增, 比如 1.5的2次方 1.5的3次方


自定义重试组件

我们可以自己实现重试组件feign.Retryer接口,也可以使用OpenFeign自带的重试组件feign.Retryer.Default,假如我们使用自带的重试组件,我们只要定义一个配置类,配置Retryer的Bean,覆盖默认的Retryer.NEVER_RETRY;
下面例子是配置每次重试间隔是100ms,最大重试间隔是1s, 重试次数是2次
@Componentpublic class CustomFeignConfig {
public Integer retryPeriod = 100; public Integer retryMaxPeriod = 1000; public Integer maxRetryAttempts = 2;
//自定义重试组件,覆盖OpenFeign默认的Retryer.NEVER_RETRY; @Bean public Retryer retryer() { return new Retryer.Default(retryPeriod, retryMaxPeriod, maxRetryAttempts); }}

总结

1、OpenFeign提供了重试组件,默认是不重试的

2、feign.Retryer.Default的实际重试次数是maxAttempts-1

OpenFeign重试组件分析完了,对你有没有帮助呢?

后面将继续分析OpenFeign的其他组件能力。

哈哈都看到这里了,关注我一起学习吧!!

原文作者:服务端技术栈;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-03-08

  • 博文量
    97
  • 访问量
    41429