[Spring Cloud [source interpretation] of how to configure a variety of good OpenFeign timeout! ]

About Feign timeout Detailed:

In the Spring Cloudmicro-service architecture, most companies are using the Open Feigncall room service, and relatively simple business using the default configuration will not have much problem, but if the business is more complex services to be more complicated business computing that background is likely to appear Read Timeoutthis exception.

1, the fuse time-out on hystrix

If you Feignopen a blown fuse must be reset timeout because the default timeout is too short fuse, and only one second, which easily lead to calls business services not completed and the timeout was blown.

How to configure time-out fuse:

#Feign如何开启熔断
feign.hystrix.enabled=true

#是否开始超时熔断,如果为false,则熔断机制只在服务不可用时开启(spring-cloud-starter-openfeign中的HystrixCommandProperties默认为true)
hystrix.command.default.execution.timeout.enabled=true

#设置超时熔断时间(spring-cloud-starter-openfeign中的HystrixCommandProperties默认为1000毫秒)
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000

Note: For hystrixthe application.propertiesconfiguration is not suggested, but HystrixCommandPropertieswill get in.

// 构造函数
protected HystrixCommandProperties(HystrixCommandKey key, HystrixCommandProperties.Setter builder, String propertyPrefix) {
        
    // .... 省略很多其他配置
  
    // propertyPrefix:hystrix,key:default
    this.executionTimeoutInMilliseconds = getProperty(propertyPrefix, key, "execution.isolation.thread.timeoutInMilliseconds", builder.getExecutionIsolationThreadTimeoutInMilliseconds(), default_executionTimeoutInMilliseconds);
}

// 具体获取属性的方法
private static HystrixProperty<String> getProperty(String propertyPrefix, HystrixCommandKey key, String instanceProperty, String builderOverrideValue, String defaultValue) {
   return HystrixPropertiesChainedProperty.forString().add(propertyPrefix + ".command." + key.name() + "." + instanceProperty, builderOverrideValue).add(propertyPrefix + ".command.default." + instanceProperty, defaultValue).build();
}

2, on the Ribbon timeout.

FeignCalls default is to use Ribbonload balancing, so we also need to know about the Ribbontimeout.

①, Feign call link

Feign look at whether there is a request to use Ribbon timeout, and how to read the timeout Ribbon?

(1)、org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient#execute

(2)、com.netflix.client.AbstractLoadBalancerAwareClient#executeWithLoadBalancer(S, com.netflix.client.config.IClientConfig)

(3)、org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory#create

    ​创建Client,这里会判断对应ClientName的链接Client是否创建过,如果创建过复用之前的Client;
    如果不存在则创建一个并且放入cache缓存。
public FeignLoadBalancer create(String clientName) {
        FeignLoadBalancer client = this.cache.get(clientName);
        if(client != null) {
            return client;
        }
        IClientConfig config = this.factory.getClientConfig(clientName);
        ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
        ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class);
        // 判断是否有重试
        client = loadBalancedRetryFactory != null ? new RetryableFeignLoadBalancer(lb, config, serverIntrospector,
            loadBalancedRetryFactory) : new FeignLoadBalancer(lb, config, serverIntrospector);
        this.cache.put(clientName, client);
        return client;
    }

(4)、com.netflix.client.AbstractLoadBalancerAwareClient#executeWithLoadBalancer(S, com.netflix.client.config.IClientConfig)

    ​负载均衡器抽象类

(5)、org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer#execute

​   Feign的负载均衡器实现类。到这里我们可以看到,连接超时和读超时的配置都在这里:
    如果application.properties配置文件中的超时时间不为空,则使用配置的超时时间。
    如果为空则使用默认值,而从FeignLoadBalancer的构造函数可以看到,默认值也是取的RibbonProperties的默认超时时间。
public RibbonResponse execute(RibbonRequest request, IClientConfig configOverride)
            throws IOException {
    Request.Options options;
    // 设置超时时间。,如果orride的配置为空,则用默认值
    if (configOverride != null) {
        RibbonProperties override = RibbonProperties.from(configOverride);
        options = new Request.Options(
            override.connectTimeout(this.connectTimeout),
            override.readTimeout(this.readTimeout));
    }
    else {
        options = new Request.Options(this.connectTimeout, this.readTimeout);
    }
    // 发起请求
    Response response = request.client().execute(request.toRequest(), options);
    return new RibbonResponse(request.getUri(), response);
}

// 构造函数
public FeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig, ServerIntrospector serverIntrospector) {
    super(lb, clientConfig);
    this.setRetryHandler(RetryHandler.DEFAULT);
    this.clientConfig = clientConfig;
    this.ribbon = RibbonProperties.from(clientConfig);
    RibbonProperties ribbon = this.ribbon;
    this.connectTimeout = ribbon.getConnectTimeout();
    this.readTimeout = ribbon.getReadTimeout();
    this.serverIntrospector = serverIntrospector;
}

②, Ribbon default timeout

In the RibbonClientConfigurationmiddle:

public static final int DEFAULT_CONNECT_TIMEOUT = 1000;
public static final int DEFAULT_READ_TIMEOUT = 1000;

③, how to customize the Ribbon timeout

First, RibbonPropertiesthe source timeout read as follows:

public Integer getConnectTimeout() {
    return (Integer)this.get(CommonClientConfigKey.ConnectTimeout);
}

public Integer getReadTimeout() {
    return (Integer)this.get(CommonClientConfigKey.ReadTimeout);
}

Then, you can CommonClientConfigKeysee the name of two timeout:

// ConnectTimeout:
public static final IClientConfigKey<Integer> ConnectTimeout = new CommonClientConfigKey<Integer>("ConnectTimeout") {};

// ReadTimeout:
public static final IClientConfigKey<Integer> ReadTimeout = new CommonClientConfigKey<Integer>("ReadTimeout") {};

Then, in IClientConfigthe default implementation class: DefaultClientConfigImplit can be found Ribbonas the prefix

public static final String DEFAULT_PROPERTY_NAME_SPACE = "ribbon";

So in the end Ribbonthe so configured timeout:

ribbon.ConnectTimeout=5000
ribbon.ReadTimeout=5000

to sum up

How to configure Hystrixand Ribbontimeout it?
In fact, there is a routine. Because Feignof request: in fact Hystrix+ Ribbon. HystrixIn the outermost layer, and then Ribbon, finally there is httpa request. so. HystrixThe fuse must be greater than Ribbonthe ( ConnectTimeout+ ReadTimeout). If Ribbonit turned retry mechanism, but also multiplied by the corresponding number of retries, to ensure that Ribbonwhen the request was not over, Hystrixthe time will not be blown out.

Guess you like

Origin www.cnblogs.com/Howinfun/p/12149982.html