Dubbo源码解析 --- DIRECTORY和ROUTER

Dubbo源码解析 --- DIRECTORY和ROUTER


今天看一下DirectoryRouter

我们直接从代码看起(一贯风格),先看后总结,对着总结再来看,相信会收获很多。我们先看com.alibaba.dubbo.config.ReferenceConfigcreateProxy

if (urls.size() == 1) {
	invoker = refprotocol.refer(interfaceClass, urls.get(0));
}
复制代码

这里我们之前说过了,根据扩展点,我们知道这里的protocol目前是RegistryProtocol,点进去:

return doRefer(cluster, registry, type, url);
复制代码

这里的cluster同样是扩展点,点进去:

RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
directory.setRegistry(registry);
directory.setProtocol(protocol);
// all attributes of REFER_KEY
Map<String, String> parameters = new HashMap<String, String>(directory.getUrl().getParameters());
URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, parameters.remove(Constants.REGISTER_IP_KEY), 0, type.getName(), parameters);
if (!Constants.ANY_VALUE.equals(url.getServiceInterface())
        && url.getParameter(Constants.REGISTER_KEY, true)) {
    registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
            Constants.CHECK_KEY, String.valueOf(false)));
}
directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
        Constants.PROVIDERS_CATEGORY
                + "," + Constants.CONFIGURATORS_CATEGORY
                + "," + Constants.ROUTERS_CATEGORY));

Invoker invoker = cluster.join(directory);
ProviderConsumerRegTable.registerConsuemr(invoker, url, subscribeUrl, directory);
return invoker;
复制代码

这里出现了第一个东西:DIRECTORY,这里会用clusterjoin方法生成一个InvokerInvoker invoker = cluster.join(directory);,这里的clusterdebug一下,是FailoverCluster,生成的就是FailoverClusterInvoker。这里我们都没有发现这个Directory的作用,先别急,我们至少知道了AbstractClusterInvoker中有一个Directory的实例。

再看我们的AbstractClusterInvokerinvoke方法,这是Dubbo所有集群invoker的入口:

checkWhetherDestroyed();
LoadBalance loadbalance;
//注意这里
List<Invoker<T>> invokers = list(invocation);
if (invokers != null && invokers.size() > 0) {
    loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
            .getMethodParameter(invocation.getMethodName(), Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE));
} else {
    loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(Constants.DEFAULT_LOADBALANCE);
}
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
return doInvoke(invocation, invokers, loadbalance);
复制代码

这里有个list方法,返回的是invoker集合,doInvoke方法下沉到了子类,之前我们说过,这里会根据负载均衡策略选出一个invoker执行,那么我们看下list方法是如何选取invoker集合的:

//使用directory去选取
List<Invoker<T>> invokers = directory.list(invocation);
return invokers;
复制代码

点进去进入到AbstractDirectorylist方法:

List<Invoker<T>> invokers = doList(invocation);
//本地的routers
List<Router> localRouters = this.routers; // local reference
if (localRouters != null && localRouters.size() > 0) {
    for (Router router : localRouters) {
        try {
            if (router.getUrl() == null || router.getUrl().getParameter(Constants.RUNTIME_KEY, false)) {
                invokers = router.route(invokers, getConsumerUrl(), invocation);
            }
        } catch (Throwable t) {
            logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
        }
    }
}
复制代码

继续看一下doList,这里同样下沉到子类,子类有两个,分别是:RegistryDirectoryStaticDirectory,这两个的区别我们别的文章再说,这里简单提一下:RegistryDirectory中的invoker集合是动态的(实现了NotifyListener接口),而StaticDirectory中的invoker集合是固定的。

那么StaticDirectory返回的集合就是固定的,而RegistryDirectory是动态的,我们在注册中心对invoker做改动,都会引起RegistryDirectoryinvoker集合的变化。

这里我们大概就能理解这个Directory,实际上,这个东西就是Invoker的集合。

doList结束,下面就出现了我们说的Router,默认有三种实现:ConditionRouterMockInvokersSelector(虽然叫Selector)和ScriptRouter。这篇文章先不具体展开讨论每种Router的实现方式。

router返回的并不是一个Invoker,而是invoker集合,我们可以认为,router的作用就是把Directory中符合路由规则的invoker筛选出来,然后在这些invoker中,根据负载均衡策略和集群容错策略执行invoke方法。

总结一下: Directorinvoker的集合,是AbstractClusterInvoker的属性,可以认为是本集群下的所有InvokerRouter:从Directory中挑选出符合要求的Invoker集合。 LoadBalance:从Router挑选的invoker中再选出其中一个作为最终选择去执行invoke方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值