深入理解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.execute方法中有调用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;@RibbonClientNameprivate String name = "client";
@Bean@ConditionalOnMissingBeanpublic 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 {@Overridepublic <T> DefaultClientConfigImpl set(IClientConfigKey<T> key, T value) {properties.put(key.key(), value);return this;}protected Object getProperty(String key) {//这里enableDynamicProperties一定是trueif (enableDynamicProperties) {String dynamicValue = null;DynamicStringProperty dynamicProperty = dynamicProperties.get(key);//dynamicProperty是nullif (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超时参数同时存在时)

在这里插入图片描述

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

玄机平台应急响应—apache日志分析

1、前言 apache的日志一共有两个&#xff0c;一个是access.log&#xff0c;这个日志记录了所有对Web服务器的访问&#xff0c;被入侵时重点排查这个。另一个是error.log&#xff0c;错误日志记录了服务器运行期间遇到的各种错误&#xff0c;以及一些普通的诊断信息&#xff0c…

纵向导航栏使用navbar-nav-scroll溢出截断问题

项目场景&#xff1a; 组件&#xff1a;Bootstrap-4.6.2、JQuery 3.7.1 测试浏览器&#xff1a;Firefox126.0.1、Microsoft Edge125.0.2535.67 IDE&#xff1a;eclipes2024-03.R 在编写CRM的工作台主页面时&#xff0c;由于该页面使用的是较旧的技术&#xff0c;所以打算使用…

安全U盘和普通U盘有什么区别?

安全U盘&#xff08;也称为加密U盘或安全闪存驱动器&#xff09;与普通U盘肯定是有一些区别的&#xff0c;从字面意思上来看&#xff0c;就能看出&#xff0c;安全U盘是能够保护文件数据安全性的&#xff0c;普通U盘没这一些功能的&#xff0c;可随意拷贝文件&#xff0c;不防盗…

Django里的ModelForm组件

ModelForm组件 自动生成HTML标签 自动读取关联数据表单验证 保留之前提交的数据 错误提示数据库进行&#xff1a;新建&#xff0c;修改 步骤如下&#xff1a; 创建类 # 在 views.py 文件里# 创建一个类 class AssetModelForm(forms.ModelForm):class Meta:model models.…

华为端云一体化开发 (起步1.0)(HarmonyOS学习第七课)

官方文献&#xff1a; 为丰富HarmonyOS对云端开发的支持、实现端云联动&#xff0c;DevEco Studio推出了云开发功能&#xff0c;开发者在创建工程时选择云开发模板&#xff0c;即可在DevEco Studio内同时完成HarmonyOS应用/元服务的端侧与云侧开发&#xff0c;体验端云一体化协…

gcc与g++的原理

程序的翻译 1 快速认识gcc/g2 程序翻译的过程2.1 预处理阶段2.2 编译阶段2.3 汇编阶段2.4 链接阶段 3 动静态库 1 快速认识gcc/g 首先我们需要在linux系统中安装对应的编译器gcc/g&#xff0c;安装命令如下&#xff08;centos7环境下&#xff09;&#xff1a; gcc: yum instal…

算法金 | 不愧是腾讯,问基础巨细节 。。。

大侠幸会&#xff0c;在下全网同名「算法金」 0 基础转 AI 上岸&#xff0c;多个算法赛 Top 「日更万日&#xff0c;让更多人享受智能乐趣」 最近&#xff0c;有读者参加了腾讯算法岗位的面试&#xff0c;面试着重考察了基础知识&#xff0c;并且提问非常详细。 特别是关于Ada…

GIGE 协议摘录 —— GVCP 协议(二)

系列文章目录 GIGE 学习笔记 GIGE 协议摘录 —— 设备发现&#xff08;一&#xff09; GIGE 协议摘录 —— GVCP 协议&#xff08;二&#xff09; GIGE 协议摘录 —— GVSP 协议&#xff08;三&#xff09; GIGE 协议摘录 —— 引导寄存器&#xff08;四&#xff09; GIGE 协议…

抢人!抢人!抢人! IT行业某岗位已经开始抢人了!

所谓抢滩鸿蒙&#xff0c;人才先行。鸿蒙系统火力全开后&#xff0c;抢人已成鸿蒙市场的主题词&#xff01; 智联招聘数据显示&#xff0c;春节后首周&#xff0c;鸿蒙相关职位数同比增长163%&#xff0c;是去年同期的2.6倍&#xff0c;2023年9-12月鸿蒙相关职位数同比增速为3…

Oracle EBS AP发票验证-计税期间出现意外错误解决方法

系统版本 RDBMS : 12.1.0.2.0 Oracle Applications : 12.2.6 问题症状: **打开发票题头或发票行“税详细信息”**错误提示如下: 由于以下原因而无法针对"税"窗口中所做的修改更新 Oraclee Payables信息: 尚未为税率或帐户来源税率设置可退回税/应纳税额帐户。请…

Mac下载Homebrew

通过command空格搜索终端打开 直接输入 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 然后输入电脑密码 然后直接回车等待安装完成 注意⚠️&#xff1a;如果出现报错/opt/homebrew/bin is not in your PATH…

yum进阶——配置yum源

一、yum概述 yum的主要作用 解决依赖关系 自动安装 自动升级 各个系统中的安装软件服务 CentOS7 &#xff1a;yum -y 安装 rpm包 CentOS8 &#xff1a;dnf&#xff08;yum的升级版&#xff09;&#xff0c; Ubantu(22.04) &#xff1a;apt -y 安装&#xff0c;安装源为/…

民主测评要做些什么?

民主测评&#xff0c;作为一种重要的民主管理工具&#xff0c;旨在通过广泛征求群众意见&#xff0c;对特定对象或事项进行客观、公正的评价。它不仅是推动民主参与、民主监督的重要手段&#xff0c;也是提升治理效能、促进社会和谐的有效途径。以下将详细介绍民主测评的主要过…

GNU Radio实现OFDM Radar

文章目录 前言一、GNU Radio Radar Toolbox编译及安装二、ofdm radar 原理讲解三、GNU Radio 实现 OFDM Radar1、官方提供的 grc①、grc 图②、运行结果 2、修改后的便于后续可实现探测和通信的 grc①、grc 图②、运行结果 四、资源自取 前言 本文使用 GNU Radio 搭建 OFDM Ra…

分水岭算法分割和霍夫变换识别图像中的硬币

首先解释一下第一种分水岭算法&#xff1a; 一、分水岭算法 分水岭算法是一种基于拓扑学的图像分割技术&#xff0c;广泛应用于图像处理和计算机视觉领域。它将图像视为一个拓扑表面&#xff0c;其中亮度值代表高度。算法的目标是通过模拟雨水从山顶流到山谷的过程&#xff0…

代码解读 | Hybrid Transformers for Music Source Separation[03]

一、背景 接着上一篇代码解读 | Hybrid Transformers for Music Source Separation[02]文章&#xff0c;继续对Hybrid Transformer Demucs 代码进行解读。 解读目标&#xff1a;明确数据从进入算法&#xff0c;在算法内部&#xff0c;以及在算法输出 这三个阶段中 数据的大小是…

如何执行VMware P2V迁移|VMware Converter和替代方案

VMware中的P2V是什么&#xff1f; 我们常说的VMware P2V其实指的就是“物理到虚拟”&#xff0c;将工作负载从物理机器转换或迁移到虚拟机&#xff08;VM&#xff09;的过程&#xff0c;能够使您无需从头开始费力地创建和配置新虚拟机。 就像您可以使用Disk2vhd执行Hyper-V物理…

如何在virtualbox上安装Linux系统(centerOS)

提示&#xff1a;共同学习 注意&#xff1a;一定要在BIOS中的虚拟化打开。 文章目录 第一步&#xff1a; 第一步&#xff1a; 启动 、显示开启 centos基础安装 ​ ​

九大微服务监控工具详解

Prometheus Prometheus 是一个开源的系统监控、和报警工具包&#xff0c;Prometheus 被设计用来监控“微服务架构”。 主要解决&#xff1a; 监控和告警&#xff1a;Prometheus 可以对系统、和应用程序进行实时监控&#xff0c;并在出现问题时发送告警&#xff1b;数据收集和…

超详细的java Comparable,Comparator接口解析

前言 Hello大家好呀&#xff0c;在java中我们常常涉及到对象的比较&#xff0c;不同于基本数据类型&#xff0c;对于我们的自定义对象&#xff0c;需要我们自己去建立比较标准&#xff0c;例如我们自定义一个People类&#xff0c;这个类有name和age两个属性&#xff0c;那么问…