【Feign/Ribbon】记录一次生产上的SpringCloudFeign的重试问题
在上周在的微供有数项目中(数据产品),需要对接企业微信中第三方应用,在使用Feign的去调用微服务的用户模块用微信的code获取access_token以及用户工厂信息时出现Feign重试超时报错的情况,通过此篇文章记录问题解决的过程。
一.问题重现:
1.SpringCloud部分依赖如下
<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.请求流程图

二.原因分析
1.整个请求的链路中,阶段2是feign请求的位置,但是yml配置文件中并没有配置feign,因此可以断定feign使用的默认的配置,问题发生时,查看feign的文档发现,feign重试默认超时时间是1s,
因此现在重新配置feign的超时时间,现有feign的配置如下
feign:
client:
config:
organization:
connectTimeout: 5000
readTimeout: 5000
其实organization表示的就是feign所调用的服务名称
connectTimeout表示建立请求连接的连接的时间(这里面包括获取请求eureka中保存的服务列表-推测)
readTimeout表示连接建立以后请求调用的时间
2.在上述配置中,通过查看organization和data服务的请求日志,发现请求都能顺利的建立,但是当阶段三去请求微信的接口一旦延迟,则会触发feign的重试进行第二次调用;
由于阶段三请求微信的接口并不是没有调用,而是由于网络或者其他原因导致的微信没有响应,但是code又已经被消费了,当阶段二携带同样的code去调用微信的接口,这时就会出现
code已经被消费
3.此时有另外一个问题就是,项目中的服务都是单实例部署,springcloud组件中feign和ribbon都有重试的功能,
Spring Cloud中Feign整合了Ribbon,但Feign和Ribbon都有重试的功能,Spring Cloud为了统一两者的行为,在C版本以后,将Feign的重试策略默认设置为 feign.Retryer#NEVER_RETRY(即永不重试)
因此Feign的调用本质还是通过ribbon去实现
feign:
client:
config:
eureka-client:
connectTimeout: 1000
readTimeout: 1000
配置二:
只配置ri'bbon
注意 这里有个坑MaxAutoRetriesNextServer这个参数如果不配置为0,即使在单实例部署的情况下,仍然会发生重试1次,因此如果不想发生重试,则需要手动配置
MaxAutoRetriesNextServer=0和MaxAutoRetries=0
ribbon:
ReadTimeout: 4000
ConnectionTimeout: 4000
OkToRetryOnAllOperations: true
MaxAutoRetriesNextServer: 0 # 当前实例全部失败后可以换1个实例再重试,
MaxAutoRetries: 1 # 在当前实例只重试2次
配置三:
feign和ribbon都不配置,注意,经过测试后发现这里使用的是ribbon默认的超时配置,配置如下:
MaxAutoRetriesNextServer=1
MaxAutoRetries=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;
【Feign/Ribbon】记录一次生产上的SpringCloudFeign的重试问题的更多相关文章
- Feign Ribbon Hystrix 三者关系 | 史上最全, 深度解析
史上最全: Feign Ribbon Hystrix 三者关系 | 深度解析 疯狂创客圈 Java 分布式聊天室[ 亿级流量]实战系列之 -25[ 博客园 总入口 ] 前言 疯狂创客圈(笔者尼恩创建的 ...
- 【OOM】记录一次生产上的OutOfMemory解决过程
一.项目架构 SpringCloud Dalston.SR1 + SpringBoot 1.5.9 + Mysql +Redis + RabbitMQ 所有的业务模块的应用服务都部署在同一个服务器, ...
- springcloud微服务实战:Eureka+Zuul+Feign/Ribbon+Hystrix Turbine+SpringConfig+sleuth+zipkin
相信现在已经有很多小伙伴已经或者准备使用springcloud微服务了,接下来为大家搭建一个微服务框架,后期可以自己进行扩展.会提供一个小案例: 服务提供者和服务消费者 ,消费者会调用提供者的服务,新 ...
- 记录CentOS 7.4 上安装MySQL&MariaDB&Redis&Mongodb
记录CentOS 7.4 上安装MySQL&MariaDB&Redis&Mongodb 前段时间我个人Google服务器意外不能用,并且我犯了一件很低级的错误,直接在gcp讲服 ...
- 生产上数据库大量的latch free 导致的CPU资源耗尽的问题的解决
中午的时候,我们生产上的某个数据库,cpu一直居高不下 通过例如以下的sql语句,我们查看当时数据库的等待,争用的情况: select s.SID, s.SERIAL#, 'kill -9 ' || ...
- SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]
目录 前提:本篇是基于 SpringCloud+Eureka+Feign+Ribbon的简化搭建流程和CRUD练习[1] 的修改与拓展 1.修改consumer的CenterFeign.java,把返 ...
- SpringCloud的服务消费者 (二):(rest+feign/ribbon)声明式访问注册的微服务
采用Ribbon或Feign方式访问注册到EurekaServer中的微服务.1.Ribbon实现了客户端负载均衡,Feign底层调用Ribbon2.注册在EurekaServer中的微服务api,不 ...
- Linux(2)---记录一次线上服务 CPU 100%的排查过程
Linux(2)---记录一次线上服务 CPU 100%的排查过程 当时产生CPU飙升接近100%的原因是因为项目中的websocket时时断开又重连导致CPU飙升接近100% .如何排查的呢 是通过 ...
- 记录一次线上bug
记录一次线上bug,总的来说就是弱网和重复点击.特殊值校验的问题. 测试场景一: 在3g网络或者使页面加载速度需要两秒左右的时候,输入学号,提交学生的缴费项目,提交完一个 学生的缴费后, ...
随机推荐
- 更改EFI分区位置
我是win10 + arch 双系统,并且efi分区用的是win10自动创建的(大小100m),所以这些空间很快就不够用了(内核和initramfs都放在了ESP分区当中) 我原本是直接把win的ef ...
- 【Java进阶面试系列之一】哥们,你们的系统架构中为什么要引入消息中间件?
转: [Java进阶面试系列之一]哥们,你们的系统架构中为什么要引入消息中间件? **这篇文章开始,我们把消息中间件这块高频的面试题给大家说一下,也会涵盖一些MQ中间件常见的技术问题. 这里大家可以关 ...
- CVE-2017-12149-JBoss 5.x/6.x 反序列化
漏洞分析 https://www.freebuf.com/vuls/165060.html 漏洞原理 该漏洞位于JBoss的HttpInvoker组件中的 ReadOnlyAccessFilter 过 ...
- mysql连接不上本地服务器或者localhost:3306报错
今天初学MySQL数据库就遇到问题: 主要是本地服务器登录问题 workbench里双击那个connection出现的 解决方法: 1:看一看防火墙,这是最常见的,这种主要是防火墙限制了访问,可能是安 ...
- Linux入门视频笔记三(常用工具集)
一.全局变量(Linux中的全局变量指在整个系统中都能用的变量) 1.USER:当前登录系统的用户的用户名 2.HOME:当前用户的主目录 cd $HOME 或 cd ~可以进入用户主目录 3.PAT ...
- P1049_装箱问题(JAVA语言)
思路:动态规划的背包问题.使箱子剩余空间最小,也就是使箱内装的物品体积达到最大,我们可将物品的体积视为价值,然后按照01背包问题求解即可. //直接上模板 题目描述 有一个箱子容量为VV(正整数,0 ...
- 仿String()构造器函数 【总结】
需求 实现以下方法: 控制台结果: 需求分析: 首先确定new调用的this和什么对象绑定,如果跟默认返回的对象绑定肯定做不到 [ ] 这样的访问,所以要在构造器内部返回一个包装过的数组 1.leng ...
- AutoPy开发文档
AutoPy 简介 AutoPy是为python开发者提供的一个安卓插件,由路飞大佬开发维护,主要功能为了实现使用python在安卓端完成一些操作,例如点击,滑动,返回 准备 安装AutoPy.apk ...
- Android Studio中Switch控件有关 thumb 和 track 用法
•任务 •属性 android:track:底部的图片(灰->绿) android:thumb:设置 Switch 上面滑动的滑块,也就是上图中的白色圆形滑块 •switch_thumb 点击 ...
- 经典变长指令ModR/M
变长指令 不是所有的指令都是,看到opcode就知道有多长(定长指令),当指令中出现内存操作对象的时候,就需要在操作码后面附加一个字节来进行补充说明,这个字节被称为ModR/M. 该字节的8个位被分成 ...