【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网络或者使页面加载速度需要两秒左右的时候,输入学号,提交学生的缴费项目,提交完一个 学生的缴费后, ... 
随机推荐
- 在Windows服务中添加定时器
			创建windows服务: 在VisualStudio中用C#创建一个Windows服务,微软MSDN参考地址: http://msdn.microsoft.com/zh-cn/library/zt39 ... 
- 使用python进行接口自动化测试,批量执行测试用例
			工作中,使用python的requests库进行接口自动化测试是一个比较不错的选择,今天就以某网站的免费接口为例,展示以get请求进行批量执行测试用例.话不多说直接开讲 分析一下接口信息, 请求地址: ... 
- 微信小程序一周时间表
			<view class="dateView"> <image class="dateLeft" bindtap="prevWeek& ... 
- POJ-3660(Floyd算法)
			Cow Contest POJ-3660 1.本题考察的是最短路,用的算法是Floyd算法 2.如果一个结点和剩余的n-1个结点都有关系,那么可以确定其排名 3.需要注意的是,判断是否有关系时,反向关 ... 
- Apache配置 10. 访问控制-禁止解析PHP
			(1)简述 对于使用PHP语言编写的网站,有一些目录是有需求上传文件的.如果网站代码有漏洞,让黑客上传了一个用PHP写的木马,由于网站可以执行PHP程序,最终会让黑客拿到服务器权限. 为了避免这种情况 ... 
- SQL练习——LeetCode解题和总结(1)
			只用于个人的学习和总结. 178. Rank Scores 一.表信息 二.题目信息 对上表中的成绩由高到低排序,并列出排名.当两个人获得相同分数时,取并列名次,且名词中无断档. Write a SQ ... 
- 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
			题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 输入描述: 输 ... 
- python之Click的简单应用
			一.介绍 Click是一个Python包,用于以可组合的方式创建漂亮的命令行界面,只需要很少的代码.这是"命令行界面创建工具包".它具有高度可配置性,但具有开箱即用的合理默认值. ... 
- java四种字符串拼接方式
			1.直接用"+"号 2.使用String的方法concat 3.使用StringBuilder的append 4.使用StringBuffer的append 
- 通过xshell实现内网linux上公网yum、apt-get安装软件
			环境:在内网,我的机器可上网,内网服务器不可上网,本来在我机器上开个代理,服务器直接通过我机器上网就可以,奈何网络配置太复杂,目前只有ssh端口可通. 先安装ccproxy软件,配置http监听端口为 ... 
