风也温柔

计算机科学知识库

java 重试机制 关于Ribbon重试机制的坑

  一、问题

  在一次管理后台数据导入接口中,发现在大数量导入的情况下java 重试机制 关于Ribbon重试机制的坑,数据会出现重复写入的问题。后经调试发现导入接口实际上被调用了两次。初步猜测可能是Feign或的重试机制导致的。也就是管理后台服务调用业务服务,由于业务服务数据导入执行耗时较长导致超时,从而后台服务进行了重试导致。

  后台服务配置如下:

  <pre class="brush: html; toolbar: false">#Ribbon配置

Ribbon更新服务注册列表的频率

ribbon.ServerListRefreshInterval=2000

请求连接的超时时间

ribbon.ConnectTimeout=3000

请求处理的超时时间

ribbon.ReadTimeout=10000
复制代码</pre>

  二、分析

  跟踪源码,在中配置了重试相关的策略,如果.ions配置为true,则任何请求方法都进行重试,.ions配置为false时,GET请求方式也会进行重试,非GET方法只有在连接异常时才会进行重试。

  <pre class="brush: html; toolbar: false">@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler (

    RibbonRequest request, IClientConfig requestConfig){
// 如果OkToRetryOnAllOperations配置为true,则任何请求方法/任何异常的情况都进行重试
if (this.ribbon.isOkToRetryOnAllOperations()) {
    return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),
            requestConfig);
}
// OkToRetryOnAllOperations配置为false时(默认为false)
// 非GET请求,只有连接异常时才进行重试
if (!request.toRequest().method().equals("GET")) {
    return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(),
            requestConfig);
    // GET请求任何情况/任何异常都重试
} else {
    return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),
            requestConfig);
}

}
复制代码</pre>

  通过上面的分析,我们可以知道并不是配置了.ions=false就不会进行重试,对于GET请求还是会进行重试的,而在我们的系统中并没有对的重试机制做特殊的配置java 重试机制,也就是用的默认值。重试机制默认配置如下:

  <pre class="brush: html; toolbar: false">#同一实例最大重试次数,不包括首次调用。默认值为0
ribbon.MaxAutoRetries = 0

同一个服务其他实例的最大重试次数,不包括第一次调用的实例。默认值为1

ribbon.MaxAutoRetriesNextServer = 1

是否所有操作都允许重试。默认值为false

ribbon.OkToRetryOnAllOperations = false
复制代码</pre>

  由于rver配置默认值为1,而我们的导入接口恰巧又是GET请求,在业务服务接口数据处理超时的情况下,所以会自动重试一次。

  三、解决方案

  首先GET请求是用于数据查询类接口的请求方式,像涉及到数据插入/更新/删除等操作接口不应该用GET请求方式java 重试机制,在我们的数据导入接口中使用的是GET请求方式,所以此处是存在问题的。

  像在一般的系统中,建议关闭的重试机制,如果非得开启重试,那么系统的各个接口一定要保证接口的幂等性,否则可能会导致接口逻辑被执行多次的情况,在一些重要数据的场景带来的影响将是灾难性的。

  要关闭的重试将上面的rver配置为0即可,后调整的完整配置如下:

  <pre class="brush: html; toolbar: false">#Ribbon配置

Ribbon更新服务注册列表的频率

ribbon.ServerListRefreshInterval=2000

请求连接的超时时间

ribbon.ConnectTimeout=3000

请求处理的超时时间

ribbon.ReadTimeout=10000

同一实例最大重试次数,不包括首次调用。默认值为0

ribbon.MaxAutoRetries = 0

同一个服务其他实例的最大重试次数,不包括第一次调用的实例。默认值为1

ribbon.MaxAutoRetriesNextServer = 0

是否所有操作都允许重试。默认值为false

ribbon.OkToRetryOnAllOperations = false
复制代码</pre>

  如果文章对你有帮助的话,给文章点个赞吧。

  如果有写得不正确的地方,欢迎指出。

  文章来源:http://www.zyiz.net/tech/detail-139266.html