SpringCloud -- Ribbon默认重试机制

背景

项目中ServiceA 调用 ServiceB中接口时,

ServiceB处理超时长时间未返回数据,结果显示最终ServiceB中接收到ServiceA的两次请求,导致数据重复写入。

初步分析是Feign或者Ribbon的重试机制导致的,但当前项目中并未特别设置重试相关的配置,配置文件配置为

ribbon:
  ConnectTimeout: 10000 # 连接超时时间(ms)
  ReadTimeout: 10000 # 通信超时时间(ms)

场景模拟/分析

ServiceA Controller

    @GetMapping(value = "/hi")
    public String sayHi(@RequestParam String name) {
        return serviceHi.sayHiFromClientServiceHi(name);
    }

    @PostMapping(value = "/hipost")
    public String sayHiPost(@RequestBody JSONObject paramJsonObject) {
        return serviceHi.sayHiPostFromClientServiceHi(paramJsonObject);
    }


ServiceB Controller

    @GetMapping("/hi")
    public String testGet(@RequestParam(value = "name", defaultValue = "forezp") String name) throws InterruptedException {
        log.info("be called, param is {}",name);
        Thread.sleep(11000L);
        return "hi " + name + " ,i am from port:" + port;
    }

    @PostMapping("/hipost")
    public String testPost(@RequestBody JSONObject paramJsonObject) throws InterruptedException {
        log.info("be called, param is {}",paramJsonObject.getStr("name"));
        Thread.sleep(11000L);
        return paramJsonObject.getStr("name");
    }

调用Hi接口后 返回ReadTimeOut ServiceB 被调用两次

调用HiPost接口后 返回ReadTimeOut ServiceB 被调用一次跟踪源码发现,getRequestSpecificRetryHandler 方法中做了重试相关策略的配置, 当okToRetryOnAllOperations为false且方法不为Get时, 不会进行重试,否则都会默认进行重试调用

    public RequestSpecificRetryHandler getRequestSpecificRetryHandler(final S request, final IClientConfig requestConfig) {
        if (this.okToRetryOnAllOperations) {
            return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
        } else {
            return !request.getContext().getMethod().equals("GET") ? new RequestSpecificRetryHandler(true, false, this.getRetryHandler(), requestConfig) : new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
        }
    }

解决方案

通过为以下字段进行配置修改来关闭重试

ribbon:
  ConnectTimeout: 10000 # 连接超时时间(ms)
  ReadTimeout: 10000 # 通信超时时间(ms)
  OkToRetryOnAllOperations: false # 是否对所有操作重试 默认为false
  MaxAutoRetriesNextServer: 0 # 同一服务不同实例的重试次数 默认为1
  MaxAutoRetries: 0 # 同一实例的重试次数 默认为0

ConnectTimeOut: 建立连接所用的时间

ReadTimeOut: 连接建立后从服务器读取到资源的时间

最大重试次数  = (1+maxAutoRetries)*(1+maxAutoRetriesNextServer)次

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值