【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网络或者使页面加载速度需要两秒左右的时候,输入学号,提交学生的缴费项目,提交完一个 学生的缴费后, ...
随机推荐
- Spring MVC 配置记录
目录 1.从pom.xml配置Maven文件开始 2.web.xml 3.springmvc-config.xml 4.controller 使用 idea 编辑器 + Maven + spring ...
- 《深入浅出WPF》-刘铁猛学习笔记——XAML
XAML是什么? XAML是微软公司创造的一种开发语言,XAML的全称是 Extensible Application Markup Language,即可拓展应用程序标记语言. 它由XML拓展而来, ...
- WPF 基础 - 点击事件的执行顺序及 Button 点击事件的特殊性
1. 点击事件的执行顺序 PreviewMouseLeftButtonDown PreviewMouseDown MouseLeftButtonDown MouseDown PreviewMouseL ...
- idea添加本地文件约束(DTD)
当我们做 xml 文件配置的时候,需要对其进行约束的配置 例如: hibernate 如果我们在联网的情况下是可以不添加配置文件约束的,红框内的 URL 会自动帮我们从网络上加载约束文件,但是没有网络 ...
- golang 并发运算时主线程先运行完,子线程运行没结束的问题记录
代码如下: blocks,err:= mgo.FindBlocks(batch) //获得当前批次下的矿体信息 cubes:= BlockCutting(blocks[0],x,y,z,nest) f ...
- 详解 ZooKeeper 数据持久化
本文作者:HelloGitHub-老荀 Hi,这里是 HelloGitHub 推出的 HelloZooKeeper 系列,免费开源.有趣.入门级的 ZooKeeper 教程,面向有编程基础的新手. 项 ...
- python编写自己的base64加解密工具
0x00 Base64编码的用途 在网络传输中,不是所的的内容都是可打印字符,其中绝大多数数据是不可见字符,base64可以基于64个可打印字符来表示这些带有不可打印字符的传输数据. 0x01 Bas ...
- Redis入门到放弃系列-redis安装
Redis是什么? Redis is an open source (BSD licensed), in-memory data structure store, used as a database ...
- Ubuntu之软件包管理 (最全最精)
Centos与Ubuntu的关系 * CentOS之前的地位:Fedora稳定版-->发布-->RHEL稳定版-->发布-->CentOS * CentOS如今的地位:Fedo ...
- 开源一个比雪花算法更好用的ID生成算法(雪花漂移)
比雪花算法更好用的ID生成算法(单机或分布式唯一ID) 转载及版权声明 本人从未在博客园之外的网站,发表过本算法长文,其它网站所现文章,均属他人拷贝之作. 所有拷贝之作,均须保留项目开源链接,否则禁止 ...