概念解释
申请重试,次要用来解决以下几方面问题:
- 我的项目公布降级,服务单个节点重启时,局部经网关路由的申请呈现连贯回绝、服务不可用的状况
- 某个服务节点因内存溢出、硬件故障等起因down掉时的申请无响应状况
- 连接池满、线程死锁造成的相应迟缓状况
- 网络稳定导致的局部节点无奈连贯状况
单次申请经由路由转发后达到服务节点,如呈现上述问题,可采纳转发至服务集群中的其余节点的形式来进步服务强壮度。
实现计划
因为对于线上环境的应用服务,根本全副采纳了多节点部署形式,而在某次申请未能胜利时,对繁多节点反复申请的成功率低于向其余节点申请,因而该计划应用切换节点重试的形式。
Zuul
通过引入spring-retry包,并开启zuul.retryable: true配置开启重试,因为zuul的route依赖ribbon,需在ribbon配置节点减少对应项。残缺配置如下:
zuul: host: connect-timeout-millis: 500 socket-timeout-millis: 10000 SendErrorFilter: error: disable: true retryable: trueeureka: client: registry-fetch-interval-seconds: 3 # 刷新本地缓存工夫(30s) dev:3 test:3 pre:3 pro:5hystrix: command: default: execution: timeout: #配置命令的执行,是否会超时 enabled: true isolation: thread: #命令的执行超时工夫 超时将执行回退 timeoutInMilliseconds: 31500ribbon: ReadTimeout: 10000 ConnectTimeout: 500 MaxAutoRetries: 0 # 以后节点的重试次数 MaxAutoRetriesNextServer: 2 # 其余节点的重试次数
要害配置项:MaxAutoRetriesNextServer ,此处的2表明一次申请最大可能被解决三次,因而熔断器的超时时长应设置为单词时长的三倍。该配置项会在申请失败时,将申请forward到其余节点,如果以后注册核心中并未发现该服务的其余节点,则 间接完结申请 (此处与feign有所不同)切换到其余节点进行重试,还受影响与zuul此时持有的服务节点缓存,即使此时注册核心中存在其余节点,如果zuul持有的服务节点缓存中没有其余节点,申请也会被终止。此处把缓存节点的刷新工夫调整为3秒,来进步对于注册核心的变动相应速度
Feign
在同一注册核心环境下的服务间调用,个别采纳FeignClient的形式,Feign默认开启了重试开关,只需在ribbon配置节点增加对重试形式和次数的申明,并引入spring-retry依赖包即可应用。
Feign的重试策略,教训证发现,与Zuul环境下的成果有所不同。Feign会在单词申请失败后,随机转发申请到该服务的所有节点,蕴含曾经失败的以后节点,及时MaxAutoRetries配置项为0。
全局幂等计划
为防止反复的申请造成屡次数据处理,而产生非预期的成果,此处应用RedissonLock对申请进行束缚,来确保本次申请只会被执行一次。解决流程如下:
- 在Zuul和FeignCliient发出请求之前,向RequestHeader中增加requestId项(毫秒+随机数组成)
- 申请达到服务节点时,应用requestId+服务对应serverId创立基于redis的分布式锁,后执行对应解决流程
- 申请在超时状况下被转发到其余节点时,如果未能获取到对应规定的分布式锁,则间接返回申请超时的异样信息,并终止重试
- 解决实现,提早10s(对应单词ribbon的超时工夫)开释锁,已防止单次申请超时,重试到其余节点的同时,原节点刚好实现解决并开释锁,导致被认为申请未被解决过的状况。