深入理解feign远程调用的各种超时参数

1. 引言

在spring cloud微服中,feign远程调用可能是大家每天都接触到东西,但很多同学却没咋搞清楚这里边的各种超时问题,生产环境可能会蹦出各种奇怪的问题。
首先说下结论:
1)只使用feign组件,不使用ribbion组件,其默认feign的连接超时是10s,读超时是60s;
2) 同时使用了feign和ribbion组件,(1)若没有任何人为配置超时时间,远程调用使用ribbion的默认超时时间,连接超时、读超时都是1秒钟;(2)若同时主动配置了feign 、ribbion的超时时间,则使用配置的feign超时时间;(3)若只主动配置了feign的超时时间,则使用配置的feign超时时间;(4)若只主动配置了ribbon超时时间,则使用配置的ribbion超时时间。

2. only feign

feign本身是通过FeignClientFactoryBean 创建出来的,feign的超时配置也在方法org.springframework.cloud.openfeign.FeignClientFactoryBean#configureUsingConfiguration中。此方法properties.isDefaultToProperties()的默认值是true,我们一般也不会去改它,所以一般是执行红方框中的逻辑。(1)先执行全局配置configureUsingConfiguration(context, builder),(2)再执行属性配置类中FeignClientProperties的默认配置, (3)最后执行属性配置类FeignClientProperties中当前feign client特定的配置。这三个步骤的覆盖顺序是后者覆盖前者,也就是越往后优先级越高。默认情况下我们未做任何配置时,FeignClientProperties是空对象,也就是说此时只会执行步骤(1)的属性配置。
在这里插入图片描述
全局属性配置方法org.springframework.cloud.openfeign.FeignClientFactoryBean#configureUsingConfiguration回到spring容器中去取超时配置对象Request.Options
在这里插入图片描述在这里插入图片描述
自动配置类相应方法为我们配置了一个Request.Options对象(当spring容器中不存在此类型的bean时)
在这里插入图片描述
LoadBalancerFeignClient.DEFAULT_OPTIONS的连接超时、读超时分别是10s、60s.


public class LoadBalancerFeignClient implements Client {

	static final Request.Options DEFAULT_OPTIONS = new Request.Options();
	//.....
}	
 public static class Options {

    private final long connectTimeout;
    private final TimeUnit connectTimeoutUnit;
    private final long readTimeout;
    private final TimeUnit readTimeoutUnit;
    private final boolean followRedirects;
    //.......
     /**
     * Creates the new Options instance using the following defaults:
     * <ul>
     * <li>Connect Timeout: 10 seconds</li>
     * <li>Read Timeout: 60 seconds</li>
     * <li>Follow all 3xx redirects</li>
     * </ul>
     */
    public Options() {
      this(10, TimeUnit.SECONDS, 60, TimeUnit.SECONDS, true);
    }
    //.......

 }   

3. feign+ribbon

在feign引入ribbon负载均衡时,远程调用的feign client会用LoadBalancerFeignClient.
LoadBalancerFeignClient方法中有调用getClientConfig(options, clientName);的代码行,而IClientConfig中包含有feign和ribbion超时时间。
在这里插入图片描述
getClientConfig方法参数中的options是feign本身的超时配置,
可以看到当参数options等于DEFAULT_OPTIONS,即没有为feign主动配置超时时间这种情况,这种情况会到容器用去获取超时配置;当options不等于DEFAULT_OPTIONS,即已经为feign主动配置了超时时间这种情况下,我们会使用feign的超时时间。

IClientConfig getClientConfig(Request.Options options, String clientName) {
		IClientConfig requestConfig;
		if (options == DEFAULT_OPTIONS) {
			requestConfig = this.clientFactory.getClientConfig(clientName);
		}
		else {
			requestConfig = new FeignOptionsClientConfig(options);
		}
		return requestConfig;
	}

这个IClientConfig 在配置类org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration的配置方法ribbonClientConfig执行config.loadProperties(this.name);将配置文件中ribbion的配置信息赋值到config对象后,又执行了config.set(CommonClientConfigKey.ConnectTimeout, DEFAULT_CONNECT_TIMEOUT); config.set(CommonClientConfigKey.ReadTimeout, DEFAULT_READ_TIMEOUT);重新将连接超时、读超时重置为1000毫秒,即1秒。

@SuppressWarnings("deprecation")
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
// Order is important here, last should be the default, first should be optional
// see
// https://github.com/spring-cloud/spring-cloud-netflix/issues/2086#issuecomment-316281653
@Import({ HttpClientConfiguration.class, OkHttpRibbonConfiguration.class,
		RestClientRibbonConfiguration.class, HttpClientRibbonConfiguration.class })
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;

	/**
	 * Ribbon client default Gzip Payload flag.
	 */
	public static final boolean DEFAULT_GZIP_PAYLOAD = true;

	@RibbonClientName
	private String name = "client";
@Bean
	@ConditionalOnMissingBean
	public IClientConfig ribbonClientConfig() {
		DefaultClientConfigImpl config = new DefaultClientConfigImpl();
		config.loadProperties(this.name);
		config.set(CommonClientConfigKey.ConnectTimeout, DEFAULT_CONNECT_TIMEOUT);
		config.set(CommonClientConfigKey.ReadTimeout, DEFAULT_READ_TIMEOUT);
		config.set(CommonClientConfigKey.GZipPayload, DEFAULT_GZIP_PAYLOAD);
		return config;
	}
	//....
	}
    
}

我们在看看DefaultClientConfigImpl的怎么处理属性的。
可以看出上边RibbonClientConfiguration.ribbonClientConfig方法中设置的超时时间,它们被放在DefaultClientConfigImpl#properties中的,而取配置属性的底层方法都是getProperty(String key),所以在没有为feign配置超时时间时,ribbon的取值时先取当前指定ribbon client的超时时间,若不存在则取全局ribbon的超时时间,若还是不存在,则取DefaultClientConfigImpl#properties中的默认值1秒。

public class DefaultClientConfigImpl implements IClientConfig {


    @Override
    public <T> DefaultClientConfigImpl set(IClientConfigKey<T> key, T value) {
        properties.put(key.key(), value);
        return this;
    }
 protected Object getProperty(String key) {
 		//这里enableDynamicProperties一定是true
        if (enableDynamicProperties) {
            String dynamicValue = null;
            DynamicStringProperty dynamicProperty = dynamicProperties.get(key);
            //dynamicProperty是null
            if (dynamicProperty != null) {
                dynamicValue = dynamicProperty.get();
            }
            if (dynamicValue == null) {
            //到配置文件中取当前client的'clientName.ribbion.ReadTimeout'这种格式的属性
                dynamicValue = DynamicProperty.getInstance(getConfigKey(key)).getString();
                if (dynamicValue == null) {
                            //到配置文件中取全局'ribbion.ReadTimeout'这种格式的属性
                    dynamicValue = DynamicProperty.getInstance(getDefaultPropName(key)).getString();
                }
            }
            if (dynamicValue != null) {
                return dynamicValue;
            }
        }
        //DefaultClientConfigImpl类中定义的默认值
        return properties.get(key);
    }

}

LoadBalancerFeignClient#execute 方法中的lbClient(clientName)创建了一个负载均衡器RetryableFeignLoadBalancer,且此负载均衡期中的config就是上边RibbonClientConfiguration#ribbonClientConfig配置方法中所对应的IClientConfig.

private FeignLoadBalancer lbClient(String clientName) {
		return this.lbClientFactory.create(clientName);
	}
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 = this.loadBalancedRetryFactory != null
				? new RetryableFeignLoadBalancer(lb, config, serverIntrospector,
						this.loadBalancedRetryFactory)
				: new FeignLoadBalancer(lb, config, serverIntrospector);
		this.cache.put(clientName, client);
		return client;
	}

现在回到LoadBalancerFeignClient#execute方法块调用负载均衡的
return lbClient(clientName) .executeWithLoadBalancer(ribbonRequest, requestConfig).toResponse();的核心实现RetryableFeignLoadBalancer#execute

在这里插入图片描述
FeignLoadBalancer是RetryableFeignLoadBalancer的父类型,构造RetryableFeignLoadBalancer时调用的构造方法new RetryableFeignLoadBalancer(lb, config, serverIntrospector, this.loadBalancedRetryFactory)会调用父类的public FeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig, ServerIntrospector serverIntrospector) 方法,而RibbonClientConfiguration#ribbonClientConfig配置方法中所对应的IClientConfig会传入此构造方法的clientConfig参数,因此这里的this.connectTimeout this.readTimeout都是ribbon的超时时间。
configOverride是feign超时配置或ribbon超时配置,而ribbon.connectTimeout(this.connectTimeout)this.connectTime超时参数是作为默认值的,所以说ribbon超时参数是会被覆盖掉,它的优先级低(feign、ribbon超时参数同时存在时)

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/674801.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

超强算力 Orange Pi Kunpeng Pro 开发板基础测评与体验

目录 开箱体验资源简介系统启动连接网络登录系统通过桌面登录通过串口登录通过 SSH 登录配置散热风扇 算力测试MNIST示例MBNET示例 体验总结 大家好&#xff0c;我是 Hello 阿尔法&#xff0c;有幸接到 CSDN 的邀请参与 Orange Pi Kunpeng Pro 开发板的测评活动&#xff0c;本文…

图片怎么快速转换大小?在线将图片改小的方法

目前在网上平台上传图片时&#xff0c;比较常见的一个问题就是图片太大导致无法正常上传&#xff0c;需要调整图片大小到平台的要求后才可以正常使用。那么如何将图片压缩到需要使用的大小呢&#xff1f; 图片大小转换现在可以使用在线改图片大小的工具会更加的简单的快捷&…

贝锐向日葵分组策略:减少重复操作,提升管理效率

面对大数量级的IT设备&#xff0c;如何高效实施管理是运维的关键所在&#xff0c;如何快速准确的对大量的设备按需分组&#xff0c;则是管理精准触达的第一步。 但是&#xff0c;传统的分组方式应付少量设备还可行&#xff0c;设备数量级一旦来到上千台甚至更多时&#xff0c;…

数据结构——排序【上】

前言&#xff1a; 今天我们开始学习排序。为了方便大家理解和练习&#xff0c;排序一共分为两节进行讲解&#xff0c;在该章节中会复习学习过的排序&#xff0c;和讲解新的排序&#xff0c;还望读者能从中又好的体验。 一、冒泡排序 冒泡排序作为基础排序&#xff0c;在我们学…

配置网页版的SQL Developer : Oracle Database Actions

我们知道SQL Developer有三种形式&#xff1a; 桌面版&#xff0c;这个最常用命令行版&#xff0c;即SQLcl网页版&#xff0c;即SQL Developer Web&#xff0c;最新的名字叫Oracle Database Actions&#xff0c; 本文讲述3&#xff0c;如何配置SQL Developer网页版。 第一步…

儿童有声挂图的芯片AD156—云信通讯

有声挂图是一种结合了图像和声音的媒体形式&#xff0c;用户可以触发图像上的声音&#xff0c;从而获得与图像内容相关的音频信息。这种融合了视觉和听觉的交互方式&#xff0c;既满足了人们对美感和观感的需求&#xff0c;又提高了信息传递的效果和效率。 有声挂图作为孩子的…

SmartEDA助力精准模拟电路性能,抢占市场先机,引领行业革新

在电子工程领域&#xff0c;模拟电路的性能优劣直接关系到产品的竞争力和市场占有率。随着科技的飞速发展&#xff0c;传统的设计方法已难以满足日益增长的精度和效率要求。在这一背景下&#xff0c;SmartEDA作为一款高效、精准的电子设计自动化工具&#xff0c;正以其独特的优…

(文章复现)基于主从博弈的售电商多元零售套餐设计与多级市场购电策略

参考文献&#xff1a; [1]潘虹锦,高红均,杨艳红,等.基于主从博弈的售电商多元零售套餐设计与多级市场购电策略[J].中国电机工程学报,2022,42(13):4785-4800. 1.摘要 随着电力市场改革的发展&#xff0c;如何制定吸引用户选择的多类型零售套餐成为提升售电商利润的研究重点。为…

三合一00

题目链接 三合一 题目描述 注意点 0 < stackNum < 2 解答思路 可以使用一个一维数组存储三个栈的元素&#xff0c;其中idx存储的是第一个数组中的元素&#xff0c;idx 1存储的是第二个数组中的元素&#xff0c;idx 2存储的是第三个数组中的元素&#xff0c;所以除…

视频剪辑软件怎么操作?5个实用的视频剪辑器分享给你

六一儿童节&#xff0c;家长们都希望记录下孩子成长的每一个精彩瞬间。 然而&#xff0c;视频剪辑往往需要花费大量的时间和精力&#xff0c;对于忙碌的家长们来说&#xff0c;这无疑是一项挑战。幸运的是&#xff0c;随着科技的发展&#xff0c;一键视频剪辑工具的出现&#…

鹏哥C语言复习——const和static

目录 const讲解 1、const 放在*的左边 2、const 放在*的右边 static讲解 1、static修饰局部变量 2、extern关键字 3、static修饰全局变量 4、static修饰函数 const讲解 const int n 10; n 0; 如上述代码&#xff0c;代码运行后会报错&#xff0c;会提示&#xff1a…

Fiink的简单学习一

一 相关大数据概念 1.1 根据时间 1.实时计算&#xff1a; 数据实时处理&#xff0c;结果实时存储 是一种持续、低时延、事件触发的任务 2.离线计算&#xff1a; 数据延迟处理&#xff0c;结果N1模式(昨天的数据今天存储) 是一种批量、高时延、主动发起的计算任务 1.2 处…

B端管理系统:深色系界面能够给用户带来什么感觉?

深色系的B端界面通常会给用户带来一种严肃、专业、稳重的感觉。这种界面设计通常会使用深色的背景和明亮的文字、图标&#xff0c;给人一种沉稳的视觉效果。 用户在使用深色系的B端界面时&#xff0c;可能会感到界面设计非常注重数据和信息的展示和分析&#xff0c;具有高度的…

Esxi_FAQ_2024.6.3

问题1-内存设置无效 问题&#xff1a; 内存设置无效: 内存预留 (sched.mem.min) 应该等于内存大小 (32768设置的内存容量) 原因&#xff1a; 是因为直通了nvme硬盘&#xff0c;在没有直通nvme硬盘时&#xff0c;不预留内存开机也不会报错。 解决&#xff1a; 需要全部预留内存…

小程序项目创建与Vant-UI引入

一&#xff0c;创建小程序项目 AppID可先用测试号&#xff1b; 模板来源选择 ’全部来源‘ &#xff0c;’基础‘ 。模板一定JS开头的&#xff1b; vant-weapp 官网 vant-Weapp 二&#xff0c;下载vant-weapp 组件 1&#xff0c;在新项目中打开 ’调试器‘&#xff1b; 2…

【大学物理实验】速通双语版

0首先&#xff0c;我们要学什么&#xff1f;outlook&#xff01; 1measurement 2system error&random error 3significant figures 4uncertainty of direct measurement and indirect measurement 5data processing 1 measurement Important points to remember&#…

文件夹批量改名每个不一样?文件夹批量命名的6种工具!(新)

在日常工作和学习中&#xff0c;我们经常需要处理大量的文件夹&#xff0c;并对它们进行有序的命名和管理。手动一个一个地改名不仅效率低下&#xff0c;而且容易出错。幸运的是&#xff0c;现在有许多工具可以帮助我们实现文件夹的批量重命名&#xff0c;确保每个文件夹的名称…

MySQL—函数—函数小结

一、引言 前面博客我们已经学完了MySQL的函数&#xff0c;下面快速的对MySQL的函数做一个小结。 在讲解了MySQL的函数的时候&#xff0c;主要有四个方面&#xff1a; 1、字符串函数 &#xff08;1&#xff09;CONCAT&#xff1a;字符串连接 &#xff08;2&#xff09;LOWER、…

下载旧版postman(无需要登录,无需联网,即可轻松使用postman)

https://www.filehorse.com/download-postman/old-versions/page-3/ 人工智能学习网站 https://chat.xutongbao.top

docker+vue云服务器打包镜像相关操作

dockervue云服务器打包镜像相关操作 容器化部署似乎成了当前一个非常主流的趋势&#xff0c;无论是前端还是后端&#xff0c;流行的操作就是给你一个镜像地址&#xff0c;让你自己去拉取镜像并运行镜像。这似乎是运维的工作&#xff0c;但是在没有专有运维的情况下&#xff0c…