Spring Cloud Feign+Ribbon的超时机制
在一个项目中(数据产品),需要对接企业微信中第三方应用。在使用 Feign 的去调用微服务的用户模块用微信的 code 获取 access_token 以及用户工厂信息时出现 Feign 重试超时报错的情况,通过此篇文章记录问题解决的过程。
一、问题重现
1. Spring Cloud 部分依赖如下
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.3.RELEASE</version></parent><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Dalston.SR1</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-feign</artifactId></dependency>
2.微信相关的接口文档
前端通过企业 id,配置好回调域名之后,调用微信的 API 去获取 code。见文档:
https://work.weixin.qq.com/api/doc/90000/90135/91022
注意:code只能用一次,见文档,因此获取到的 access_token 需要缓存起来,项目中是缓存到redis中的,用于后续的消息推送等等功能。

3.请求流程图

二、原因分析
首先,整个请求的链路中,阶段 2 是 feign 请求的位置,但是 yml 配置文件中并没有配置 feign。因此可以断定,feign 使用了默认的配置。问题发生时,查看 feign 的文档发现,feign 重试默认超时时间是 1s。
因此现在重新配置 feign 的超时时间,现有 feign 的配置如下:
feign:client:config:organization:connectTimeout: 5000readTimeout: 5000
其中,
-
organization 表示的就是 feign 所调用的服务名称。
-
connectTimeout表示建立请求连接的连接的时间(这里面包括获取请求 Eureka 中保存的服务列表——推测)
-
readTimeout表示连接建立以后请求调用的时间。
其次,在上述配置中,通过查看 organization 和 data 服务的请求日志,发现请求都能顺利建立。但是,当阶段三去请求微信的接口一旦延迟,则会触发 feign 的重试进行第二次调用。
由于阶段三请求微信的接口并不是没有调用,而是由于网络或者其他原因导致的微信没有响应,但是 code 又已经被消费了,当阶段二携带同样的 code 去调用微信的接口,这时就会出现 code 已经被消费。
最后,此时有另外一个问题就是,项目中的服务都是单实例部署,Spring Cloud 组件中 Feign 和 Ribbon 都有重试的功能。 Spring Cloud 中 Feign 整合了 Ribbon,但 Feign 和 Ribbon 都有重试功能。Spring Cloud为了统一两者的行为,在 C 版本以后,将 Feign 的重试策略默认设置为 feign.Retryer#NEVER_RETRY(即永不重试)。因此 Feign 的调用本质还是通过 Ribbon 去实现。
三、相关配置测试
经过测试后,发现 Feign 和 Ribbon 的配置都能实现超时熔断。
版本号:SpringCloud Greenwich.SR1
配置一、只配置 Feign 相关配置,即 Feign 覆盖了 Ribbon 默认的超时时间配置
但是注意,该配置会触发 Ribbon 重试。
feign:client:config:eureka-client:connectTimeout: 1000readTimeout: 1000
配置二、只配置 Ribbon
注意:这里有个坑,MaxAutoRetriesNextServer 这个参数如果不配置为 0,即使在单实例部署的情况下,仍然会发生重试 1 次。因此如果不想发生重试,则需要手动配置 MaxAutoRetriesNextServer=0和MaxAutoRetries=0。
ribbon:ReadTimeout: 4000ConnectionTimeout: 4000OkToRetryOnAllOperations: trueMaxAutoRetriesNextServer: 0 # 当前实例全部失败后可以换1个实例再重试,MaxAutoRetries: 1 # 在当前实例只重试2次
配置三、Feign和 Ribbon 都不配置
注意:经过测试后发现这里使用的是ribbon默认的超时配置,配置如下。
MaxAutoRetriesNextServer=1MaxAutoRetries=0
public LoadBalancerContext(ILoadBalancer lb) {this.clientName = "default";this.maxAutoRetriesNextServer = 1;this.maxAutoRetries = 0;this.defaultRetryHandler = new DefaultLoadBalancerRetryHandler();this.okToRetryOnAllOperations =DefaultClientConfigImpl.DEFAULT_OK_TO_RETRY_ON_ALL_OPERATIONS;this.lb = lb;}
版本号:SpringCloud Dalston.SR1 与 Greenwich.SR1 的测试结论一致
注意:Dalston.SR1 ribbon 组件默认的超时时间
public static final int DEFAULT_READ_TIMEOUT = 5000;public static final int DEFAULT_CONNECT_TIMEOUT = 2000;
Greenwich.SR1 Ribbon 组件默认的超时间
public static final int DEFAULT_CONNECT_TIMEOUT = 1000;public static final int DEFAULT_READ_TIMEOUT = 1000;
相关文章:
Spring Cloud Feign+Ribbon的超时机制
在一个项目中(数据产品),需要对接企业微信中第三方应用。在使用 Feign 的去调用微服务的用户模块用微信的 code 获取 access_token 以及用户工厂信息时出现 Feign 重试超时报错的情况,通过此篇文章记录问题解决的过程。 一、问题重…...
使用docker 搭建nginx + tomcat 集群
创建3个Tomcat容器,端口分别映射到 8080,8081,8082,使用数据卷挂载,分别将宿主机目录下的 /opt/module/docker/tomcat3/ROOT1/,/opt/module/docker/tomcat3/ROOT2/,/opt/module/docker/tomcat3/ROOT2/ 挂载到 容器内部…...
从Spring的角度看Memcached和Redis及操作
目录 Memcached和Redis的区别 适用场景 Memcached配置使用 Redis配置使用 在SpringBoot的框架里,有直连Redis的SDK却没有Memcached的,可见相比地位。不过各有各的适应场景,Redis这个单线程模型确实非常强。 Memcached和Redis的区别 共同…...
【C语言学习】C语言的基础数据类型
一、数据类型 1.整型 short(短整型) int(整型 long(长整型) long long(长整型)2.浮点型 float(单精度型) double(双精度型) long double3.字符类型 char…...
使用AIGC工具提升安全工作效率
新钛云服已累计为您分享760篇技术干货 在日常工作中,安全人员可能会涉及各种各样的安全任务,包括但不限于: 开发某些安全工具的插件,满足自己特定的安全需求;自定义github搜索工具,快速查找所需的安全资料、…...
HBase概述
HBase 一 HBase简介与环境部署 1.1 HBase简介&在Hadoop生态中的地位 1.1.1 什么是HBase HBase是一个分布式的、面向列的开源数据库HBase是Google BigTable的开源实现HBase不同于一般的关系数据库, 适合非结构化数据存储 1.1.2 BigTable BigTable是Google设计的分布式…...
el-popover全屏不显示(bug记录)
我做了一个el-table全屏展示的功能, 然后里面的el-popover在全屏后无法展示, 刚开始以为是写唯一的key或者ref, 发现写了也不行, 后来以为要写’:append-to-body“false”, 最后发现是我的外层的层级写得太高了; position: fixed; z-index: 9999; <div class"box"…...
react中使用redux-persist做持久化储存
某天下午折腾着玩的 – 笔记 安装相关依赖 npm install reduxjs/toolkit redux-persist redux react-redux// store.jsx import { configureStore, getDefaultMiddleware } from "reduxjs/toolkit"; import { persistStore, persistReducer } from "redux-per…...
【leetcode】203. 移除链表元素(easy)
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头节点 。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* Lis…...
InfiniBand、UCIe相关思考
InfiniBand、UCIe相关思考 内容1、InfiniBandInfiniBand是什么?InfiniBand的来历是什么?InfiniBand为什么重要?InfiniBand相较于Ethernet区别?同领域内还有其他哪些技术?InfiniBand中RDMA是种什么技术? 内容…...
[C++项目] Boost文档 站内搜索引擎(3): 建立文档及其关键字的正排 倒排索引、jieba库的安装与使用...
之前的两篇文章: 第一篇文章介绍了本项目的背景, 获取了Boost库文档 🫦[C项目] Boost文档 站内搜索引擎(1): 项目背景介绍、相关技术栈、相关概念介绍…第二篇文章 分析实现了parser模块. 此模块的作用是 对所有文档html文件, 进行清理并汇总 🫦[C项目] …...
el-date-picker回显问题解决记录
el-date-picker回显问题记录 组件结构 <el-date-pickerv-model"time"type"datetimerange"range-separator"至"start-placeholder"开始日期"end-placeholder"结束日期"value-format"yyyy-MM-dd HH:mm:ss":defau…...
Linux中的特殊进程(孤儿进程、僵尸进程、守护进程)
一、孤儿进程 1)父进程退出,子进程不退出,此时子进程被1号(init)进程收养,变成孤儿进程。 2)孤儿进程会脱离终端控制,且运行在后端,不能用ctrlc杀死后端进程,…...
【分布式能源选址与定容】光伏、储能双层优化配置接入配电网研究(Matlab代码实现)
目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码、数据、讲解 💥1 概述 由于能源的日益匮乏,电力需求的不断增长等,配电网中分布式能源渗透率不断提高,且逐渐向主动配电网方…...
《cuda c编程权威指南》04 - 使用块和线程索引映射矩阵索引
目录 1. 解决的问题 2. 分析 3. 方法 4. 代码示例 1. 解决的问题 利用块和线程索引,从全局内存中访问指定的数据。 2. 分析 通常情况下,矩阵是用行优先的方法在全局内存中线性存储的。如下。 8列6行矩阵(nx,ny)(…...
mysql 、sql server 常见的区别
NULL 处理 MySQL IFNULL(col , val) SQL Server ISNULL(col,val) 表名、列名等 一般不推荐用保留字 ,如果非要保留字 MySQL 用用着重号,即 反引号 包括 select col from GROUP SQL Server 用用着重号…...
查找特定元素——C++ 算法库(std::find_if)
std::find_if函数在C++中的实际使用案例非常广泛,以下是一些常见的用法示例: 1、在容器中查找满足特定条件的元素: #include <iostream> #include <vector> #include <algorithm>bool isOdd(int num) {...
D3JS教程_编程入门自学教程_菜鸟教程-免费教程分享
教程简介 D3是Data-Driven Documents的缩写,D3.js是一个基于数据管理文档的资源JavaScript库。 D3 是最有效的数据可视化框架之一。它允许开发人员在 HTML、CSS 和 SVG 的帮助下在浏览器中创建动态的交互式数据可视化。数据可视化是将过滤后的数据以图片和图形的形…...
Android入门教程||Android 架构||Android 应用程序组件
Android 架构 Android 操作系统是一个软件组件的栈,在架构图中它大致可以分为五个部分和四个主要层。 Linux内核 在所有层的最底下是 Linux - 包括大约115个补丁的 Linux 3.6。它提供了基本的系统功能,比如进程管理,内存管理,设…...
C语言二进制数据和16进制字符串互转
知识点:结构体中的“伸缩型数组成员”(C99新增) C99新增了一个特性:伸缩型数组成员(flexible array member),利用这项特性声明的结构,其最后一个数组成员具有一些特性。第1个特性是,该数组不会…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...
