摘要: 今天在生产环境发生了数据库进程卡死的现象,除了sql因为全量更新,没加索引的原因,最主要还是我们的接口的服务器端接口出现问题了。忽视了更新接口的幂等性,以及调用方feign client的重试,导致接口重复执行。万幸的是数据已经修复,花了几个小时跟踪feign和ribbon的源码,把其原理彻底搞明白了。
feign是netflix提供的服务间基于http的rpc调用框架,在spring cloud得到广泛应用。默认情况下,一个feign client是在hystrix断路器中执行,并利用ribbon进行软负载选择远程target service,所以可以想象出一个feign client的层次架构是包裹的层次,hystrix控制整个rpc从调用到方法返回,而ribbon控制从选址到socket返回,关于它们的超时设置,请参考我上一篇博客:SpringCloud重试机制配置。
今天先不讨论hystrix,仅从feign在spring cloud中应用容易踩到坑和从源码debug的角度看执行过程。我们先来填坑,看看这个配置:
这是ribbon在github wiki上的给我们的默认配置,OKToRetryOnAllOperations的意义是无论是请求超时或者socket read timeout都进行重试,
这个OKToRetryOnAllOperations=true我建议改成false或者不设,为什么?我们直接上源码分析:
这是feign初始化它的ribbon重试控制器,它的逻辑是如果设置了OKToRetryOnAllOperations这个参数为true,第一个if的构造函数就设置为true,这就比较危险了,如果接口是post或者put请求,这是进行修改操作,如果服务器长时间不返回,客户端发生socket read timeout会进行重试,如果服务器接口没做幂等性,这个后果自己想想。继续看后面两个判断,得出的结论是:如果是Get请求设置为OKToRetryOnAllOperations=true不影响,因为只涉及到读操作,如果是其他http方法,默认只会在socket还没建立连接时进行重试,比如突然网络抖动或者一台服务实例挂了,这是没问题的,因为只保证了服务器端执行一次(还是建议涉及到修改的接口做好幂等性)。
关于超时再提一下两个配置ribbon.ConnectTimeout和ReadTimeout,根据自己服务调用情况,慎重进行设置,我的建议是ReadTimeout可以稍微设大点(同时注意hystrix线程池超时时间)。
下面我们分析下feign的执行过程和重试机制,下面这个图是我简易画的,这是总体概览
1、一个feign请求开始,通过动态代理的方式包裹了一层feign retryer逻辑,控制最外层的feign自身的重试机制:
2、continueOrPropagate是控制是否重试和跳出上层死循环的最终出口:
3、必要的ribbon设置,并调用真实执行逻辑
4、在AbstractLoadBalancerAwareClinet中执行,LoadBalancerCommand中控制ribbon选取server、重试、记录执行状态、封装错误返回,这都是利用RXJava的观察者模式来做的
- 第一个catch控制ribbon请求的Exception
- 第二个catch控制整个一轮ribbon重试(ribbon.MaxAutoRetries、ribbon.MaxAutoRetriesNextServer)下来,仍然异常。
- 回到方法调用入口的catch,进行feign的retryer的逻辑,决定是整体再重试还是直接抛出异常跳出循环(默认是5次重试)
5、默认情况下,在feign.Client.Default的内部类里进行真实的http请求,默认是用Java的网络api(这块可以替换掉自己写,比如使用:netty)
总结下,注意我们的接口请求方式,设置合适的超时时间,OKToRetryOnAllOperations这个参数慎用。如果对网络请求性能要求较高,可以在适当位置重写源码。
转自:https://blog.csdn.net/tianyaleixiaowu/article/details/79128879
相关推荐
主要介绍了Spring Cloud Feign统一设置验证token实现方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
第二个红框,order-service是我们要重试的依赖服务 第一次调用失败后,对本实例进行MaxAutoRetries次调用 第三个红框,之前在讲原理时着重讲
springcloud feign 服务消费者 类似 webservice ====== http://knight-black-bob.iteye.com/blog/2356222
springcloud feign整合hystrix 示例,希望对大家有所帮助
除了Feign自带的注解外它还支持JAX-RS注解,SpringCloud又为Feign增加了对SpringMVC注解的支持,同时为了能够使用和Spring Web中默认使用的相同的httpMessageConverter,SpringCloud集成了Ribbon和Eureka,用来在...
主要介绍了Spring Cloud Feign 自定义配置(重试、拦截与错误码处理) 实践,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
springcloud整合openFeign,包括feign的基本使用、传参、指定特定的服务器、负载均衡等使用方法。 模块有: springcloud-feign-api springcloud-feign-consumer springcloud-feign-provider springcloud-feign-...
主要介绍了spring cloud feign实现远程调用服务传输文件的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
SpringCloud之Feignhttps://blog.csdn.net/u012081441/article/details/80763738
SpringCloud中关于Feign的常见问题总结,包括常用的请求注解、@PathVariable、FeignClient多参数的构造等
本篇文章主要介绍了SpringCloud之Feign示例详解,详细的介绍了Feign简介和使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
文档:https://blog.csdn.net/jameshadoop/article/details/82026772
本篇文章主要介绍了Spring Cloud Feign简单使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
SpringCloud之四 负载均衡Feign,使用Feign进行微服务的负载均衡处理
springcloudf feign 服务间相互调用示例
SpringCloud eureka zuul feign 负载均衡 微服务
spring cloud eureka zuul ribbon hystrix feign config 示例代码
18.Spring Cloud中Feign配置详解 19.Spring Cloud中的API网关服务Zuul 20.Spring Cloud Zuul中路由配置细节 21.Spring Cloud Zuul中异常处理细节 22.分布式配置中心Spring Cloud Config初窥 23.Spring Cloud ...
微服务中通常使用 Feign 作为服务消费者,那么如何使用 Feign 接口传输文件呢?这篇文章主要介绍了Spring Cloud Feign文件传输的示例代码,感兴趣的小伙伴们可以参考一下