0
点赞
收藏
分享

微信扫一扫

dubbo源码分析第十九篇一dubbo负载均衡-FailoverCluster失败重试

舍予兄 2022-01-20 阅读 91

文章目录

FailoverClusterInvoker

  • 重试会重新调用list(获取提供者集合外加路由)获取最新Invoker结果,因提供者可能有变动,重新获取本地缓存,确保监听变更后的RegisterDirectory能被及时感知
  • 重试通过循环实现
 
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
    List<Invoker<T>> copyInvokers = invokers;
    checkInvokers(copyInvokers, invocation);
    String methodName = RpcUtils.getMethodName(invocation);
    获取重试次数加自身调用一次 
    int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
    if (len <= 0) {
        len = 1;
    }
    // retry loop.
    RpcException le = null; // last exception.
    List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
    Set<String> providers = new HashSet<String>(len);
    第一次加两次重试循环
    for (int i = 0; i < len; i++) {
        if (i > 0) {
            checkWhetherDestroyed();
            在进行重试前重新列举 Invoker,这样做的好处是,如果某个服务挂了, 通过调用 list 可得到最新可用的 Invoker 列表原因是register是监听zk的
            copyInvokers = list(invocation);
            check again
            checkInvokers(copyInvokers, invocation);
        }
        通过负载均衡策略选择Invoker
        Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
        invoked.add(invoker);
        RpcContext.getContext().setInvokers((List) invoked);
        try {
            Result result = invoker.invoke(invocation);
            return result;
        } catch (RpcException e) {
            if (e.isBiz()) { 
                throw e;
            }
            le = e;
        } catch (Throwable e) {
            le = new RpcException(e.getMessage(), e);
        } finally {
            providers.add(invoker.getUrl().getAddress());
        }
    }
    重试都失败则抛出异常
    throw new RpcException(le.getCode(), "Failed to invoke the method "
            + methodName + " in the service " + getInterface().getName()
            + ". Tried " + len + " times of the providers " + providers
            + " (" + providers.size() + "/" + copyInvokers.size()
            + ") from the registry " + directory.getUrl().getAddress()
            + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
            + Version.getVersion() + ". Last error is: "
            + le.getMessage(), le.getCause() != null ? le.getCause() : le);
}

总结

  • 假设配置timeout1秒,加上重试3次,一个接口就会出现3秒超时
  • 注意此场景带来的雪崩效应
举报

相关推荐

0 条评论