我的物联网项目(二十八) springcloud feign超时重试问题
最近平台有人员反应了几个问题:
1.商家充值记录有时候莫名其妙存在充值后的重复数据记录。
2.开发人员无意中提了一次我们的feign负载均衡有时候会负载到两台集群服务器都会执行。
3.定时调度去执行当日表移单要历史表,发现存储过程被调用了两次。
由于这几个问题不是同一时间段出现的,再加上是偶发性的,当初重点排查的是业务本身的代码,毫无头绪,但是随着这些问题经常的出现,需要引起重视并与解决。
在测试环境一次调试中,发现一个奇怪的现象,两台服务器A,B集群,被feign负载均衡分别各执行了一次,为了百分之百命中并重现问题,将里面的方法休眠一段时间,果然不出所料,feign负载均衡百分之百对各实例都分别执行一次。
查阅springcloud feign客户端负载均衡相关资料,springcloud的重试机制是指:负载均衡客户端Ribbon发现远程请求实例不可到达之后,去重试其他实例的过程。那么果然就是这个问题,有些服务在执行过程中由于各种原因导致超时,feign client的重试,导致接口重复执行。
解决这个问题之前也要具体问题具体分析,如果是查询操作,操作失败了进行重试是可行的,但是如果是非幂等性的写操作,如果被调用方某个实例实际中执行了写操作,仅仅是因为网络或其他原因造成了异常,调用方依然进行重试,这就是不允许的。
像上面的业务就属于非幂等性的写操作,所以将其配置成不允许重试机制。
OkToRetryOnAllOperations: false
MaxAutoRetriesNextServer: 0
原理说明:
Feign是通过内置的Ribbon进行负载均衡,并通过HTTP去访问被调用方,所以Feign的重试,其实就是Ribbon的重试。另外,我们在实际工作中使用Feign,用到Hystrix,在这里就顺便说一下Hystrix的原理。举例说明下,假如在没有Hystrix的情况下,用户一个下单操作需要调用订单、支付、物流三个服务,如果其中物流Service因为种种问题不能提供服务,即便另外两个服务都好好的,整个下单操作也会因为物流Service而阻塞住,导致下单服务崩溃。而Hystrix为每个依赖的服务配置独立的线程池并进行隔离,假设下单服务有90个线程,没有Hystrix,则因为物流Service不能提供服务,不停地重试直到90个线程全卡死。而有了Hystrix,三个依赖的服务,每个30个线程,即便物流的30个全部阻塞了,也不影响另外两个服务的线程。