zoukankan      html  css  js  c++  java
  • hystrix ,feign,ribbon的超时时间配置,以及原理分析

     背景,网上看到很多关于hystrix的配置都是没生效的,如:

     

     一.先看测试环境搭建:

     order 服务通过feign 的方式调用了product 服务的getProductInfo 接口

    //------------ order 服务的调用接口---------------
    
    @FeignClient(name ="product",fallback =ProductHystrix.class)
    @Primary
    public interface ProductService {
        @RequestMapping("/info/{id}")
        Product getProductInfo(@PathVariable("id") Integer id);
    }
    
    
    @Component
    public class ProductHystrix implements ProductService{
        @Override
        public Product getProductInfo(Integer id) {
            System.out.println("被熔断;了");
            Product product = new Product();
            product.setName("熔断了。。。。。");
    
            return product;
        }
    }
    
    // product 服务提供的接口------------------
    @Controller
    public class ProductController {
        @RequestMapping("/info/{id}")
        @ResponseBody
        @MyLogAnnotation
        public Product getProductInfo(@PathVariable("id") Integer id){
            Product product = new Product();
            product.setId(id);
            product.setName("苹果手机");
    
            return product;
        }
    }

    order 服务的application.yml 开启feign:hystrix:enabled: true
    二. Hystrix 的超时时间怎么设置:

    直接上代码:hystrix 任何相关配置都可以在下面的配置类配置,我这里修改了核心线程数和最大队列数已经超时时间

    package com.yang.xiao.hui.order.controller;
    
    import com.netflix.hystrix.*;
    import feign.Feign;
    import feign.Target;
    import feign.hystrix.HystrixFeign;
    import feign.hystrix.SetterFactory;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Scope;
    
    import java.lang.reflect.Method;
    
    
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })
    public class FeignConfig {
    
        @Bean
        @Scope("prototype")
        @ConditionalOnProperty(name = "feign.hystrix.enabled")
        public Feign.Builder feignHystrixBuilder() {
            HystrixFeign.Builder builder = HystrixFeign.builder();
            SetterFactory setterFactory= new SetterFactory(){
    
                @Override
                public HystrixCommand.Setter create(Target<?> target, Method method) {
                    String groupKey = target.name();
                    String commandKey = Feign.configKey(target.type(), method);
                    //HystrixThreadPoolProperties 线程池相关配置
                    HystrixThreadPoolProperties.Setter setter = HystrixThreadPoolProperties.Setter().withCoreSize(100).withMaxQueueSize(200);
                    //HystrixCommandProperties 熔断器相关属性配置
                    HystrixCommandProperties.Setter setter1 = HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(6000);
    
                    return HystrixCommand.Setter
                            .withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
                            .andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
                            .andThreadPoolPropertiesDefaults(setter)
                            .andCommandPropertiesDefaults(setter1);
    
    
                }
            };
            builder.setterFactory(setterFactory);
    
            return builder;
        }
    }

    启动服务:通过浏览器输入http://localhost:8674/info/3 调用order 服务

     

     跟进去看HystrixCommand的创建:

     

     由此可见线程池和熔断超时时间都已经改变了,证明我们的配置生效了

    原理分析:

    在FeignClientsConfiguration这个配置类中有一段代码:

     然后跟进看到默认的对象:

     

     HystrixCommandProperties对象有个默认的超时时间,默认是1s:

     那么,我们根据上面的分析,当容器中存在HystrixFeign.builder就不会再创建该bean 了,所以我们可以自己创建一个HystrixFeign.builder 然后调用setterFactory(SetterFactory setterFactory)来修改默认的配置,也就是上面我们自己定义的配置类

    熔断器的熔断时间是从调用下面的方法开始计算的:

    三.feign超时时间怎么设置?

    我们继续跟进刚才的调用方法:

     

     在这里默认连接时间是10s,读取时间是60s,那么这个类是怎么创建的呢?

     

     

     从上面可以知道,Options对象默认已经有个时间配置了,然而我们继续跟踪代码:

     

     

     我们看这里:

     

     Options对象经过getClientConfig(options, clientName) 方法,就从10s的连接时间变成了1s,60s的读取时间也变成了1s,上面源码分析可以知道:

    如果我们配置了feign的超时时间,那么就会以我们配置的时间为准,如果没有配置,那么就取ribbon的超时时间,2者只能有一个生效,而ribbon默认超时时间是1秒

    继续跟进:

     

     

     

     上述代码可见,feign或者ribbon所配置的超时时间,最终都是在HttpUrlConnection中生效

    那么,我们如何修改feign的配置时间呢?

    我们回到这里:

     这里说了,如果容器没有该bean才会默认创建,那我们就自己创建一个注入到spring容器中:

    在order 服务中:

    @Configuration
    
    public class Config {
        @Bean
        public Request.Options feignRequestOptions() {
            Request.Options options = new Request.Options(2000, TimeUnit.MILLISECONDS,
                    2000, TimeUnit.MILLISECONDS,
                    true);
    
            return  options;
        }
    
    }

    重启,重新调用:

     看到配置已经生效了:

    我们这里readTimeout 设置了2秒,如果我们在product服务睡眠3s看看:

    product 服务没有睡眠时,正常情况调用结果如下:

    product 服务代码修改:

     order 服务再次调用:

     可见,跟我们想象的一样

    如果feign的超时时间设置为4s,而hystrix的熔断时间设置为2s看看:

     

     再次调用:

     重点是product服务的日志打印:

      证明order 服务熔断了,但product 服务还是被调用了,说明feign的时间设置是没问题的

    根据上面分析,Hystrix的熔断时间要大于Feign或Ribbon的connectTimeout+readTimeout

    feign的超时时间如果要在application.yml中配置,改如何配置呢:

    feign:
      hystrix:
        enabled: true
      client:
        config:
          default:
            #连接到目标的时间,此处会收到注册中心启动中的影响。设置为3秒钟,如果注册中心有明显的不在线,基本是毫秒级熔断拒绝
            connectTimeout: 3000
            #获取目标连接后执行的最长时间,设置为32秒,即服务最长时
            readTimeout: 32000

    为何能这样配置呢?

     

      我们再次启动order服务,调用跟踪:

     那ribbon的超时时间如何配置:

    ribbon:
      ReadTimeout: 3000
      ConnectTimeout: 3000

    再次启动测试:

     那么有人要问了,如果feign和ribbon同时配置,那么以谁的为准,前面已经分析过了,这里再次分析:

     重新调用跟踪:

     继续跟踪:

     

     

     最后总结:

    hystrix的熔断时间配置通过yml配置没法生效,可以通过配置类的方法来修改,feign的超时时间可以通过代码或者yml配置,ribbon的超时时间可以通过yml来配置

    feign和ribbon的超时时间只能二选一,只要feign的超时时间配置了,就以feign的为准,hystrix的超时时间要大于feign/riboon的connectTimeout+readTimeout的和

    最后一张图来总结:

     

         

  • 相关阅读:
    getopt for windows
    开源代码学习之Tinyhttpd
    GCC 中的编译器堆栈保护技术
    读《程序员的思维修炼》有感
    main之前初始化流程
    平均速度
    显示图案
    圆的面积和周长
    C#(Winform) Http 发送数据
    Android BaseAdapter的使用
  • 原文地址:https://www.cnblogs.com/yangxiaohui227/p/13031370.html
Copyright © 2011-2022 走看看