dubbo面试中比较喜欢问的两个点:服务发布和服务引用. # 人性的拷问 - 服务发布过程中做了哪些事 - dubbo都有哪些协议,他们之间有什么特点,缺省值是什么 - 什么是本地暴露和远程暴露,他们的区别 直入主题 从启动日志说起 ![]( https://img-blog.csdnimg .cn/20191124151625334.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 这里不同颜色的框将关键的地方画了出来,一共有6种颜色, 从上到下 1. 暴露本地服务 2. 暴露远程服务 3. 启动netty 4. 连接zookeeper 5. 到zookeeper注册 6. 监听zookeeper # 全局总览 先看官方文档说明 ## 服务提供者暴露一个服务的详细过程 - 服务提供者暴露服务的主过程 ![](https://img-blog.csdnimg.cn/20191124160150667.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 首先 `ServiceConfig` 类拿到对外提供服务的实际类 ref(如:HelloWorldImpl),然后通过 `ProxyFactory` 类的 `getInvoker` 方法使用 ref 生成一个 `AbstractProxyInvoker` 实例,到这一步就完成具体服务到 Invoker 的转化。 接下来就是 Invoker 转换到 Exporter 的过程。 ![](https://img-blog.csdnimg.cn/20191124161756667.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 看源码,很多人最常问的一句话就是,怎么入手,也就是切入点.那么我们还是以开头的日志为例,来找一个这个切入点 仔细看输出日志,就会发现在暴露本地服务之前,有一句很重要的日志,就是 ```bash The service ready on spring started. service: com.alibaba.dubbo.demo.DemoService, dubbo version: 2.0.0, current host: 127.0.0.1 ``` > 该打印在今年八月被移除,具体原因不明, 留待日后分析,先继续经典版本源码 > ![] > ![](https://img-blog.csdnimg.cn/2019112416565177.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 定位到了`ServiceBean`这个类 - 继承体系图 ![](https://img-blog.csdnimg.cn/20191124165857776.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) > 继续按照经典版本源码讲解,这里最新版源码由于删除了相关接口 从这个图我们看到了许多和spring有关的东西,还发现了一个重要的接口,那就是`ApplicationListener` 就是spring的事件机制(event).什么是事件机制呢? 就比如监听spring 容器初始化完成.那我们就定位到这行日志的位置,往下debug ![](https://img-blog.csdnimg.cn/20191124170659797.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20191124170708847.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20191124170721312.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 重点!!! ![](https://img-blog.csdnimg.cn/20191124171616267.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20191124171851867.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 这个dubbo.properties文件是怎么时候加载的,好像我根本没有设置,另外这个dubbo.properties文件的名字能不能改? ![](https://img-blog.csdnimg.cn/20191124195126940.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) - 同理,对于log4j.xml文件 ![](https://img-blog.csdnimg.cn/20191124195351829.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_16,color_FFFFFF,t_70) 接下来继续往下走,下面这里就是我们的第二道面试题 ![](https://img-blog.csdnimg.cn/20191124195620539.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) - 因为dubbo是支持多协议的,看文档原话 ![](https://img-blog.csdnimg.cn/20191124195642846.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) - Dubbo支持多种协议,默认使用的是dubbo协议 (https://blog.csdn.net/qq_33589510/article/details/103108713) 到了第三个面试题,也是服务发布的重点,`本地暴露和远程暴露` ![](https://img-blog.csdnimg.cn/20191124201218464.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 为什么会有本地暴露和远程暴露呢? 不从场景考虑讨论技术的没有意义是.在dubbo中我们一个服务可能既是Provider,又是Consumer,因此就存在他自己调用自己服务的情况,如果再通过网络去访问,那自然是舍近求远 因此他是有本地暴露服务的这个设计 - 本地暴露是暴露在JVM中,不需要网络通信 - 远程暴露是将ip,端口等信息暴露给远程客户端,调用时需要网络通信 ![](https://img-blog.csdnimg.cn/20191124202252323.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20191124202414239.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 从上图可知,这里用到了Adaptive, - 点进ProxyFactory查看源码 ![](https://img-blog.csdnimg.cn/20191124201927649.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) @Adaptive注解打在类上和方法上,他们是有区别的 在方法上,就会生成动态编译的Adaptive类,下面就介绍一下怎么看这个动态编译类的源码 - 首先要将这个log4j的level调整为DEBUG ![](https://img-blog.csdnimg.cn/20191124202701924.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 为什么需要调整成DEBUG, 比如下图 ![](https://img-blog.csdnimg.cn/20191124203107893.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 打开DEBUG后,我们重新启动,就会看到日志有如下输出,这段就是相关
代码,我们根据包名新建文件,如下 ![](https://img-blog.csdnimg.cn/20191124203137536.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20191124203245946.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 我们在getInvoker方法上打上断点,重启一下. ![](https://img-blog.csdnimg.cn/2019112420331334.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20191124203346500.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20191124203355960.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 由上图知道,本地暴露的url是以injvm开头的,下面来看下远程暴露,其实这个也是回答本地暴露和远程暴露区别的一个回答点.面试回答要的并不是一个满分的答案,而是从一些细节中,看出一个人,是否真的研究过源码. ![](https://img-blog.csdnimg.cn/20191124203417820.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9qYXZhZWRnZS5ibG9nLmNzZG4ubmV0,size_1,color_FFFFFF,t_70) 还是回到开头那句话,dubbo命名是很规范的,从Wr apper这个命名,其实可以和Spring的Bean Wrapper,以及装饰者设计模式联系起来.同时可以看看文档中的编码约定 # 参考 - https://www.jianshu .com/p/60a9263f2ee2 -