越努力,越幸运

朱季谦

腾讯云社区2022年度最佳作者、阿里云专家博主认证

Dubbo广播机制源码解读

总结/朱季谦

先前在测试环境遇到过一个问题,即Dubbo广播机制,在对各个提供者节点进行广播操作过程中,存在最前面的两个节点出现异常的情况,但后边的其他节点仍能正常同步的情况。我以前就知道Dubbo的Broadcast机制,先前概念里总以为这是一个当广播到某个节点若出现异常时,就会直接停止广播操作,但在Dubbo的广播机制里,却不是这样。它会先遍历所有的Invokers调用,若过程出现异常时,只会先将异常先类似日志一样记录下来,等到Invokers遍历完成后,最后才会将最后保留的异常进行抛出。

这就能解释了,为啥存在两个节点出现异常的情况下,后面的节点仍能正常被广播通知到。

接下来,我们简单看下Dubbo的Broadcast机制源码,这里的代码很好看懂——

接下来,我们简单看下Dubbo的broadcast机制源码——

public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {

    private static final Logger logger = LoggerFactory.getLogger(BroadcastClusterInvoker.class);

    public BroadcastClusterInvoker(Directory<T> directory) {
        super(directory);
    }

    @Override
    @SuppressWarnings({"unchecked", "rawtypes"})
    public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
        //通过CollectionUtils.isEmpty(invokers)检查invokers集合是否为空,若为空,抛出异常
        checkInvokers(invokers, invocation);
        //类似上下文操作保存invokers
        RpcContext.getContext().setInvokers((List) invokers);
        RpcException exception = null;
        Result result = null;
        //遍历invoker远程调用接口服务
        for (Invoker<T> invoker : invokers) {
            try {
                result = invoker.invoke(invocation);
            } catch (RpcException e) {
                //若出现异常,将异常信息进行保存
                exception = e;
                logger.warn(e.getMessage(), e);
            } catch (Throwable e) {
                exception = new RpcException(e.getMessage(), e);
                logger.warn(e.getMessage(), e);
            }
        }
        //等invokers遍历完成后,若存在异常,再对异常进行抛出
        if (exception != null) {
            throw exception;
        }
        return result;
    }

}

这里的遍历操作是单线程进行的,存在一个问题,若invokers数量很庞大,那么,将会出现广播耗时的情况,我觉得这里若invokers数据量过大时,可以通过选择有返回值的线程池并发执行。

posted @ 2022-08-10 16:56  朱季谦  阅读(415)  评论(0编辑  收藏  举报