服务发布和服务的引用到底什么实现的呢?我们追踪这个问题进行下面的学习?
首先我们通过控制台查看服务启动过程中,日志记录了什么?
通过日志看出发布的过程:①暴露本地服务 ② 暴露远程服务 ③启动netty ④ 连接zookeeper ⑤注册到zookeeper ⑥监听zookeeper
The service ready on spring started. service: com.alibaba.dubbo.demo.DemoService, dubbo version: 2.0.0, current host: 127.0.0.1
在暴露本地服务之前,输出了上述日志语句。
ServiceBean
ServiceBean 实现ApplicationListener接口监听ContextRefreshedEvent事件(容器加载完成事件)
public void onApplicationEvent(ApplicationEvent event) {
if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) {
if (isDelay() && ! isExported() && ! isUnexported()) {
if (logger.isInfoEnabled()) {
logger.info("The service ready on spring started. service: " + getInterface());
}
export();
}
}
在容器加载完成后执行export(); 开始暴露;
ServiceConfig 类
方法执行顺序:export() -> doExport() -> doExportUrls() -> doExportUrlsFor1Protocol();
export() 判断是否延迟发布,如果延迟发布会新建个Daemon线程然后调用doExport(), 否则直接调用doExport();
doExport() 给ServiceConfig 装载注册中心监控中心等。
doExportUrls()
private void doExportUrls() {
List<URL> registryURLs = loadRegistries(true);//通过配置问价获取注册地址
for (ProtocolConfig protocolConfig : protocols) { //遍历Dubbo(支持多协议的)
doExportUrlsFor1Protocol(protocolConfig, registryURLs);
}
}
-
执行loadRegistries()遍历注册中心,根据注册中心、Dubbo版本、Pid等生成要发布的URL;
URL示例: zookeeper://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=ordercenter_serviceImpl
&dubbo=2.8.4&pid=15836®istry=zookeeper×tamp=1484018365125 -
遍历服务协议,为每个协议执行doExportUrlsFor1Protocol()
doExportUrlsFor1Protocol()
此处判断进行本地暴露或者远程暴露,在dubbo中我们一个服务可能既是Provider,又是Consumer,因此就存在他自己调用自己服务的情况,如果再通过网络去访问,那自然是舍近求远,因此他是有本地暴露服务的这个设计.本地暴露是直接通过JVM通信,dubbo。所说的透明,就是指,让调用者对网络请求,编解码之类的细节透明,让我们像调用本地服务一样调用远程服务,甚至感觉不到自己在调用远程服务.
本地暴露的url是以injvm
开头的,远程暴露是以registry开头。
综上我们完成了具体服务到Invoker的转换。下篇文章将继续:Dubbo 处理服务暴露的关键就在 Invoker 转换到 Exporter 的过程