掘金 后端 ( ) • 2024-05-03 09:56
依赖 版本 open-feign、hystrix、ribbon 2.1.0.RELEASE feign-okhttp 10.1.0 archaius 0.7.6 jackson 2.17.0

1. 前置条件

  • feign.okhttp.enabled=true #feign使用OkHttpClient作为http请求框架
  • feign.hystrix.enabled=true #开启hystrix

2. 关系图

image.png

3. 超时机制

3.1 hystrix超时

  • 最上层是hystrix超时,hystrix会异步提交一个延时任务,延时时间就是配置的超时时间
  • 配置hystrix全局的超时时间
hystrix:
  command:
    # 默认的配置,如果没有独立配置,那么这个会是默认的配置
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 6000
  • [配置文件]配置具体接口的超时时间,${commandKey} 表示commandKey,比如接口位于类 HttpBinFeign,方法名为delay_3(),则commandKey=HttpBinFeign#delay_3();默认会优先读取具体接口的配置,具体接口的配置不存在则会使用默认的配置
hystrix.command.${commandKey}.execution.isolation.thread.timeoutInMilliseconds=4000

  • [@HystrixCommand]配置具体接口的超时时间
  1. 启用切面
@Configuration
public class HystrixConfiguration {

    @Bean
    public HystrixCommandAspect hystrixCommandAspect() {
        return new HystrixCommandAspect();
    }
}
  1. @HystrixCommand配置,这里用了种取巧的方式,添加上此注解会先转换为HystrixCommandProperties,然后当Feign接口封装为hystrixCommand时就会从factory中根据cacheKey获取,cacheKey就是commandKey,所以只需要保证在feign接口前面组装此配置就行。这里是取巧的方式,不确定会有什么问题- _ -
@HystrixCommand(
        commandKey = "HttpBinFeign#delay_3()",
        commandProperties = {
                @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
        }
)
public String delay_3() {
    return httpBinFeign.delay_3();
}

3.2 feign、ribbon超时配置

  • feign未配置时,请求超时按ribbon配置;若配置了feign超时,则请求超时按feign配置
  • feign全局超时配置,注意connect-timeout与read-timeout两个配置都需要配置,单独配置不生效
feign:
  client:
    config:
      # 默认配置
        default:
            connect-timeout: 1000
            read-timeout: 5000

  • 单个feign接口超时配置
  1. 优先级: 配置分为3种,分别是代码配置、默认配置、单个接口配置文件配置;

默认情况下(feign.client.defaultToProperties=true) 时配置优先级为 代码配置 -> 默认配置 -> 单个接口配置文件配置,优先级从低到高,高优先级的会覆盖低优先级的;

feign.client.defaultToProperties=false 时配置优先级为 默认配置 -> 单个接口配置文件配置 -> 代码配置;

也就是说默认情况下代码配置会被默认配置覆盖,所以如果想要针对单个接口进行配置,需要使用配置文件进行配置;当然也可以设置feign.client.defaultToProperties=false,这样代码配置的优先级最高

  1. 单个接口配置
# 这里的httpbin代表的是FeignClient中的contextId
feign.client.config.httpbin.read-timeout=2500
feign.client.config.httpbin.connect-timeout=800
  1. 单个接口代码配置,注意配置类不能使用@component注解,否则会全局生效
public class CustomFeignConfiguration {

    @Bean
    public Request.Options request() {
        return new Request.Options(1000, 3000);
    }
}

@FeignClient(name = "service-httpbin"
        , contextId = "httpbin", configuration = CustomFeignConfiguration.class
)
  • ribbon全局配置
ribbon:
  ReadTimeout: 5000 # 请求处理的超时时间
  ConnectTimeout: 2000 # 请求连接超时时间

3.3 非负载均衡下调用

  • feignClient指定url则不会走loadbalancer调用,会直接使用okHttpClient进行调用,参考关系图中[1]
  • OkHttpClient默认超时配置如下

  • 若配置了feign接口超时,则会覆盖okHttpClient配置

3.4 负载均衡下的调用

  • feignClient未指定url时会根据name找到对应的服务,走loadbalancer调用,参考关系图中[2]
  • 若指定了feign超时配置,则使用feign超时配置,否则使用ribbon超时配置

3.5 超时机制总结

  1. Hystrix配置的超时时间需要大于feign & ribbon配置的超时时间
  2. 只要配置了feign超时,那么无论是Okhttp还是ribbon的超时都会被覆盖
  3. feign超时需要同时配置connectTimeout & readTimeout
  4. 建议hystrix、feign、ribbon都配置默认的超时时间,且hystrix超时时间 > feign == ribbon
  5. 针对独立接口的配置,需要注意hystrix、feign超时都需要配置