Feign Hystrix Ribbon 超时配置原理解析

超时配置

我们发现feign、ribbon、hystrix中都有超时时间配置,每个组件中超时的具体含义是什么?在三者结合协作后,又应该如何配置?

Feign

超时配置

feign中的超时配置,针对的是一次请求时的连接时间和读取时间。

  • 执行一次请求的最长时间 = feign连接超时+feign读取超时

超时配置由Feign实例中的Options对象设置

private Options options = new Options();

默认配置下,连接超时时间是10S,读取超时时间是60S。

public Options() {
  this(10, TimeUnit.SECONDS, 60, TimeUnit.SECONDS, true);
}

重试机制

feign中还存在重试机制,重试里有一个间隔时间。在没有启用重试时,一个请求就只执行一次,完成一个请求的最长时间就是执行一次请求的最长时间。在重试策略启用时,一个请求可以经重试策略执行多次,完成一个请求的最长时间如下

  • 完成一个请求的最长时间 = (feign连接超时+feign读取超时)+ feign重试次数 * (feign重试间隔时间 + feign连接超时+feign读取超时)

重试配置由Feign实例中的Retryer对象设置

private Retryer retryer = new Retryer.Default();

默认配置下,最小间隔时间为100ms,最大间隔时间1s,最多执行5次(即失败后最多再重试4次)。

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

Ribbon

我们在feign中,Client用于请求发送,而ribbon则继承、扩展了Client,提供了一个新的实现LoadBalancerFeignClient,所以请求的发送执行其实是交由ribbon完成了。

超时配置

ribbon中的超时配置,同样针对的是一次请求时的连接时间和读取时间。但其配置逻辑不同,具体来说,

  • 如果feign中没有进行超时配置,那么使用Ribbon的超时配置。

    • 如果ribbon没有进行超时配置,那就使用默认的配置。默认配置下,连超超时时间是1000ms,读取超时时间是1000ms。
    public class RibbonClientConfiguration {
    
       /**
        * Ribbon client default connect timeout.
        */
    public static final int DEFAULT_CONNECT_TIMEOUT= 1000;
    
       /**
        * Ribbon client default read timeout.
        */
    public static final int DEFAULT_READ_TIMEOUT= 1000;   
    }
    
  • 如果feign中进行了超时配置,那么就使用feign的配置。

详细的逻辑见LoadBalancerFeignClient.getClientConfig()方法。

IClientConfig getClientConfig(Request.Options options, String clientName) {
   IClientConfig requestConfig;
   // DEFAULT_OPTIONS是一个静态对象
   if (options == DEFAULT_OPTIONS) {
      // 使用ribbon的超时配置
      requestConfig = this.clientFactory.getClientConfig(clientName);
   }
   else {
      // 使用feign的超时配置
      requestConfig = new FeignOptionsClientConfig(options);
   }
   return requestConfig;
}

DEFAULT_OPTIONS对象在FeignRibbonClientAutoConfiguration中进行了注入

@Bean
@ConditionalOnMissingBean
public Request.Options feignRequestOptions() {
   return LoadBalancerFeignClient.DEFAULT_OPTIONS;
}

使用feign配置的情况下,ribbon执行一次请求的最长时间如下

  • 执行一次请求的最长时间 = (feign连接超时+feign读取超时)

重试机制

ribbon中也存在重试机制,只是默认未启用,其重试时没有间隔时间,因为可以配置策略,在其它实例上进行重试。如果启用重试的话,ribbon中一次请求也可以多次执行,完成一次请求的最长时间如下

  • 完成一次请求的最长时间 = 重试次数 *(feign连接超时+feign读取超时)

ribbon中的重试,在网络连接失败、读取超时时才会进行,详见DefaultLoadBalancerRetryHandler。

public class DefaultLoadBalancerRetryHandler implements RetryHandler {

    @SuppressWarnings("unchecked")
    private List<Class<? extends Throwable>> retriable = 
            Lists.<Class<? extends Throwable>>newArrayList(ConnectException.class, SocketTimeoutException.class);
    
    @SuppressWarnings("unchecked")
    private List<Class<? extends Throwable>> circuitRelated = 
            Lists.<Class<? extends Throwable>>newArrayList(SocketException.class, SocketTimeoutException.class);
}

如果feign和ribbon都开启了重试机制,在发生可重试异常时,两个部分的重试机制都会生效,流程如下

  • feign第一次请求执行 -> ribbon负责具体的请求发送 -> 如果发生网络异常,ribbon进行重试,如果重试次数用完还是网络异常,则抛出异常 ->feign捕获异常后进行重试,再次请求执行

在都启用重试的情况下,以feign和ribbon中都只进行一次为例,一个请求最大的执行次数如下

  • 执行次数 = 1*(1+1)+ 1 *(1+1)= 2 + 2 =4

完成一个请求的最长时间为

  • 完成一个请求的最长时间 = 2 * (readTimeout + connectTimeout) + feign一次重试间隔时间 + 2 * (readTimeout + connectTimeout)

实际中,启用一个重试机制就可以了。

Hystrix

hystrix中的超时时间,指的是Hystrix命令在执行远程服务调用时的最大等待时间,针对的是一个请求。请求的执行由feign和ribbon完成,hystrix不关心其中的连接超时、读取超时和重试次数,只关注于这个请求执行耗时。

在进行配置时,大于feign和ribbon中完成一个请求的最长时间即可。feign和ribbon中完成一个请求的最长时间需要根据配置来进行计算,以使用feign的超时配置举例说明

  • feign和ribbon都不进行重试时,完成一个请求的最长时间 = feign连接超时+feign读取超时
  • feign进行重试,ribbon不进行重试时,完成一个请求的最长时间 = (feign连接超时+feign读取超时)+ feign重试次数 * (feign重试间隔时间 + feign连接超时+feign读取超时)

默认配置下,超时时间为1000ms,自定义配置hystrix全局执行超时时间。

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 2000# 设置超时时间
posted @   cd_along  阅读(377)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示