概念解释

  申请重试,次要用来解决以下几方面问题:

  1. 我的项目公布降级,服务单个节点重启时,局部经网关路由的申请呈现连贯回绝、服务不可用的状况
  2. 某个服务节点因内存溢出、硬件故障等起因down掉时的申请无响应状况
  3. 连接池满、线程死锁造成的相应迟缓状况
  4. 网络稳定导致的局部节点无奈连贯状况

      单次申请经由路由转发后达到服务节点,如呈现上述问题,可采纳转发至服务集群中的其余节点的形式来进步服务强壮度。

实现计划

因为对于线上环境的应用服务,根本全副采纳了多节点部署形式,而在某次申请未能胜利时,对繁多节点反复申请的成功率低于向其余节点申请,因而该计划应用切换节点重试的形式。

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对申请进行束缚,来确保本次申请只会被执行一次。解决流程如下:

  1. 在Zuul和FeignCliient发出请求之前,向RequestHeader中增加requestId项(毫秒+随机数组成)
  2. 申请达到服务节点时,应用requestId+服务对应serverId创立基于redis的分布式锁,后执行对应解决流程
  3. 申请在超时状况下被转发到其余节点时,如果未能获取到对应规定的分布式锁,则间接返回申请超时的异样信息,并终止重试
  4. 解决实现,提早10s(对应单词ribbon的超时工夫)开释锁,已防止单次申请超时,重试到其余节点的同时,原节点刚好实现解决并开释锁,导致被认为申请未被解决过的状况。