1、Directory类图
Directory是Dubbo对 集群获取可访问服务列表的一个抽象,共有两个实现类,StaticDirectory的子类是个测试类,RegistryDirectory 是对 通过注册中心获取可访问列表的Directory的实现,StaticDirectory是对多注册中心的封装。StaticDirectory中保存了多个集群的Invoker,ClusterInvoker会在后面讲到。可以这么说,RegistryDirectory才是集群可访问列表注册中心版本实现,Static是一个不变的Invoker保存,目前只用于多注册中心访问。
2、Directory核心方法
鉴于StaticDirectory是比较简单的维护List。下面只讨论RegistryDirectory的实现。
list方法是集群Invoker从Directory获取可访问Invoker的核心方法。
List<Invoker<T>> list(Invocation invocation) throws RpcException;
1、RegistryDirectory的doList方法
可以见到是通过methodInvokerMap获取可访问Invoker。那么methodInvokerMap是如何来维护映射关系的呢。
public List<Invoker<T>> doList(Invocation invocation) {
if (forbidden) {
throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "Forbid consumer " + NetUtils.getLocalHost() + " access service " + getInterface().getName() + " from registry " + getUrl().getAddress() + " use dubbo version " + Version.getVersion() + ", Please check registry access list (whitelist/blacklist).");
}
List<Invoker<T>> invokers = null;
Map<String, List<Invoker<T>>> localMethodInvokerMap = this.methodInvokerMap; // local reference
if (localMethodInvokerMap != null && localMethodInvokerMap.size() > 0) {
String methodName = RpcUtils.getMethodName(invocation);
Object[] args = RpcUtils.getArguments(invocation);
if(args != null && args.length > 0 && args[0] != null
&& (args[0] instanceof String || args[0].getClass().isEnum())) {
invokers = localMethodInvokerMap.get(methodName + "." + args[0]); // 可根据第一个参数枚举路由
}
if(invokers == null) {
invokers = localMethodInvokerMap.get(methodName);
}
if(invokers == null) {
invokers = localMethodInvokerMap.get(Constants.ANY_VALUE);
}
if(invokers == null) {
Iterator<List<Invoker<T>>> iterator = localMethodInvokerMap.values().iterator();
if (iterator.hasNext()) {
invokers = iterator.next();
}
}
}
return invokers == null ? new ArrayList<Invoker<T>>(0) : invokers;
}
2、NotifyListener接口
RegistryDirectory实现了NotifyListener接口,并且在通过Registry订阅provider,router,configuration等category时,调用RegistryService的subscribe方法,把自己注册到NotifyListener列表中,这样每当被订阅的对象发生改变,都会通知RegistryDirectory重新生成可访问Invoker列表,维护上面所说的Map。