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的和

最后一张图来总结:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

     

 

posted @   yangxiaohui227  阅读(8110)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
点击右上角即可分享
微信分享提示