乐趣区

关于java:基于ZuulFeign的请求重试及全局幂等方案

概念解释

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

  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: true

eureka:
  client:
    registry-fetch-interval-seconds: 3 # 刷新本地缓存工夫 (30s) dev:3 test:3 pre:3 pro:5
hystrix:
  command:
    default:
      execution:
        timeout: #配置命令的执行,是否会超时
          enabled: true
        isolation:
          thread: #命令的执行超时工夫  超时将执行回退
            timeoutInMilliseconds: 31500
ribbon:
  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 的超时工夫)开释锁,已防止单次申请超时,重试到其余节点的同时,原节点刚好实现解决并开释锁,导致被认为申请未被解决过的状况。
退出移动版