title: dubbo 源码解析 3
date: 2020/05/27 10:45
本节内容
远程服务发布(注册中心版)
远程服务发布
tag1 proxyFactory.getInvoker()
这部分流程和本地发布的一模一样,可以回顾一下
tag2 protocol.export()
public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
// 从Invoker 对象中获取到 url 对象
org.apache.dubbo.common.URL url = arg0.getUrl();
// 通过 url 对象获取协议
String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
if(extName == null) throw new IllegalStateException("Fail to get extension(org.apache.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
org.apache.dubbo.rpc.Protocol extension = null;
try {
// 获取到对应协议的对象 ProtocolFilterWrapper
extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
}catch(Exception e){
if (count.incrementAndGet() == 1) {
logger.warn("Failed to find extension named " + extName + " for type org.apache.dubbo.rpc.Protocol, will use default extension dubbo instead.", e);
}
extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension("dubbo");
}
// 执行协议对象的 export() 方法
return extension.export(arg0);
}
这个发布器只有在 unexport 的时候才会用到(换句话说,DestroyableExporter 相当于 new 了一个空实现的 Exporter),在服务调用的时候用的都是最上面那个 dubbo 发布的发布器。
tag2.1 doLocalExport() --> dubbo 服务发布
然后又经历了下面三个类的调用,最终到达了 DubboProtocol
DubboProtocol:
传入的 handler 是 DubboProtocol 的一个匿名内部类。
Exchanger:交换器,不知道在这里是做啥的
这里还用了装饰者模式。
Transporter:运输者,不知道在这里是做啥的
上面代码多为赋值代码,不需要多讲。我们重点关注 doOpen 抽象方法,该方法需要子类实现。下面回到 NettyServer 中。
我们看一下这个 handler,最早可以追溯到 HeaderExchanger#bind() 中的new DecodeHandler(new HeaderExchangeHandler(handler))
,其中 handler 是 DubboProtocol 的一个匿名内部类(其中 hander 本身就是 ChannelHandler 的子类,外面两层是装饰者)。
public class HeaderExchanger implements Exchanger {
public static final String NAME = "header";
...
@Override
public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
// 扩展一下 HeaderExchangeServer 的作用是开启心跳检测,检查服务是否存活
return new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))));
}
}
tag2.2 register()
tag2.2.1 registryFactory.getRegistry()
默认的组是 /dubbo 对应着 zookeeper 中存的目录
tag2.2.2 registry.register()
zookeeper 相关的地方我们就不讲了