还是先从整体架构入手,先看下Dubbo官方的架构设计图,调用方从集群中选择一个提供者时,首先得调用Directory获取Invoker列表,再根据配置的路由规则过滤掉不符合的提供者
Directory 的用途是保存 Invoker,可简单类比为 List。其实现类 RegistryDirectory 是一个动态服务目录,可感知注册中心配置的变化,它所持有的 Invoker 列表会随着注册中心内容的变化而变化。每次变化后,RegistryDirectory 会动态增删 Invoker,并调用 Router 的 route 方法进行路由,过滤掉不符合路由规则的 Invoker
官网的介绍中明确到,Directory中的Invoker列表会随着注册中心的内容的变化而变化,下面就从源码入手,分析Directory中的Invoker列表是如何变化的
Directory接口
先看下接口定义
public interface Directory<T> extends Node {
//返回接口Class
Class<T> getInterface();
//获取提供者对应的Invoker列表
List<Invoker<T>> list(Invocation invocation) throws RpcException;
}
有几种实现呢?
可以看到底层有RegistryDirectory
、StaticDirectory
两种实现
RegistryDirectory
实现了NotifyListener
接口,而NotifyListener接口的notify回调方法会在注册中心中提供者发生变化时被调用,从而达到通知RegistryDirectory更新Invoker列表的效果,它是能根据注册中心动态变化的核心所在StaticDirectory
没有实现NotifyListener
接口,因此其中Invoker列表不会改变,所以呢,要明白:Directory中的Invoker列表会随着注册中心的内容的变化而变化这句话在这里不适用。
既然我们分析的主要目标是Directory中Invoker的动态变化过程,自然需要分析RegistryDirectory的实现
AbstractDirectory
看Dubbo源码如果看到Abstract开头的抽象类,就应该联想到模板方法,什么意思?看下
AbstractDirectory的实现,其list方法做了一些公共的实现逻辑,再把具体的获取Invoker列表的方法通过调用doList交由子类实现,如果子类有很多实现,均只需按doList的抽象方法模板定制化自己的实现