Spring Cloud Ribbon和Feign重试机制

ribbon配置

ribbon全局配置

#Ribbon读取超时时间(单位:ms)
ribbon.ReadTimeout=60000
#Ribbon连接超时时间(单位:ms)
ribbon.ConnectTimeout=10000
#单服务节点重试次数
ribbon.MaxAutoRetries=0
#最大重试其他服务节点次数
ribbon.MaxAutoRetriesNextServer=0

ribbon单服务配置

sevice-id.ribbon.ReadTimeout=60000
sevice-id.ribbon.ConnectTimeout=10000
sevice-id.ribbon.MaxAutoRetries=0
sevice-id.ribbon.MaxAutoRetriesNextServer=0

ribbon重试次数=MaxAutoRetries*(MaxAutoRetriesNextServer+1)

feign client配置

feign client全局配置

#Feign读取超时时间(单位:ms)
feign.client.config.default.readTimeout=60000
#Feign连接超时时间(单位:ms)
feign.client.config.default.connectTimeout=10000

feign client单服务配置

service-id.feign.client.config.default.readTimeout=60000
service-id.feign.client.config.default.connectTimeout=10000

feign的超时时间配置主要通过Request.Option类实现:

  /*
   * Controls the per-request settings currently required to be implemented by all {@link Client
   * clients}
   */
  public static class Options {

    private final int connectTimeoutMillis;
    private final int readTimeoutMillis;
    private final boolean followRedirects;

    public Options(int connectTimeoutMillis, int readTimeoutMillis, boolean followRedirects) {
      this.connectTimeoutMillis = connectTimeoutMillis;
      this.readTimeoutMillis = readTimeoutMillis;
      this.followRedirects = followRedirects;
    }

    public Options(int connectTimeoutMillis, int readTimeoutMillis) {
      this(connectTimeoutMillis, readTimeoutMillis, true);
    }

    public Options() {
      this(10 * 1000, 60 * 1000);
    }
  }

默认的连接时间为10s,读取时间为60s,也可以通过重写FeignClient的config配置类文件的Options方法进行配置

	@Bean
    public Options options(){
        return new Request.Options(1*1000,10*1000);
    }

如果同时配置了ribbon和feign的超时时间,系统发现options的配置不是默认配置,就会生成一个新的FeignOptions覆盖原有ribbon的配置,所以feign的配置优先级会更高,最后生效的是feign,贴部分源码:

IClientConfig getClientConfig(Request.Options options, String clientName) {
		IClientConfig requestConfig;
		if (options == DEFAULT_OPTIONS) {
			requestConfig = this.clientFactory.getClientConfig(clientName);
		}
		else {
			requestConfig = new FeignOptionsClientConfig(options);
		}
		return requestConfig;
	}

Feign重试机制

feign本身也有重试机制,底层通过Retryer类实现逻辑:

public interface Retryer extends Cloneable {

  /**
   * if retry is permitted, return (possibly after sleeping). Otherwise propagate the exception.
   */
  void continueOrPropagate(RetryableException e);

  Retryer clone();

  class Default implements Retryer {

    private final int maxAttempts;
    private final long period;
    private final long maxPeriod;
    int attempt;
    long sleptForMillis;

    public Default() {
      this(100, SECONDS.toMillis(1), 5);
    }

    public Default(long period, long maxPeriod, int maxAttempts) {
      this.period = period;
      this.maxPeriod = maxPeriod;
      this.maxAttempts = maxAttempts;
      this.attempt = 1;
    }

    // visible for testing;
    protected long currentTimeMillis() {
      return System.currentTimeMillis();
    }

    public void continueOrPropagate(RetryableException e) {
      if (attempt++ >= maxAttempts) {
        throw e;
      }

      long interval;
      if (e.retryAfter() != null) {
        interval = e.retryAfter().getTime() - currentTimeMillis();
        if (interval > maxPeriod) {
          interval = maxPeriod;
        }
        if (interval < 0) {
          return;
        }
      } else {
        interval = nextMaxInterval();
      }
      try {
        Thread.sleep(interval);
      } catch (InterruptedException ignored) {
        Thread.currentThread().interrupt();
        throw e;
      }
      sleptForMillis += interval;
    }

    /**
     * Calculates the time interval to a retry attempt. 
* The interval increases exponentially with each attempt, at a rate of nextInterval *= 1.5 * (where 1.5 is the backoff factor), to the maximum interval. * * @return time in nanoseconds from now until the next attempt. */
long nextMaxInterval() { long interval = (long) (period * Math.pow(1.5, attempt - 1)); return interval > maxPeriod ? maxPeriod : interval; } @Override public Retryer clone() { return new Default(period, maxPeriod, maxAttempts); } } }

默认是重试5次,每次重试间隔100ms,最大重试间隔不超过1s
可以通过在FeignClient的config配置类中重写Retryer方法,修改Feign的重试方法和间隔时间
period重试间隔时间ms,maxPeriod最大重试间隔时间ms,maxAttempts最大重试次数(包含第一次请求,即重试次数=maxAttempts-1)

	@Bean
    public Retryer feignRetryer() {
        return new Retryer.Default(period, maxPeriod, maxAttempts);
    }

tips:Feign 和 Ribbon重试,其实二者的重试机制相互独立,并无联系。如果一个http请求,如果feign和ribbon都配置了重试机制,请求总次数 n (计算公式)为Feign 和 Ribbon 配置参数的笛卡尔积。
计算公式:n(请求总次数)=feign(默认5次) * (MaxAutoRetries+1)*(MaxAutoRetriesNextServer+1)
注意:+1是代表ribbon本身默认的请求
feign的重试机制相对来说比较鸡肋,使用Feign 的时候一般会关闭该功能。Ribbon的重试机制默认配置为0,也就是默认是去除重试机制的。

hystrix配置

#开启feign的fallback功能
feign.hystrix.enabled=true
#默认hystrix处理超时时长
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=60000

如果超过hystrix处理时间会直接抛出hystrix的异常:
Spring Cloud Ribbon和Feign重试机制_第1张图片

你可能感兴趣的:(JAVA,java,ribbon,spring)