经过了前面这么多的铺垫 , 没错 , 前面说了这么一大堆的都是铺垫 , 我们说了spi , 以及基于spring的扩展 , 这一篇就开始说说dubbo吧!
1.dubbo的配置文件解析
在第一篇的时候 , 我们运行了dubbo2.7.5(注意版本)的源码中的demo , 我们可以看看服务提供者的配置文件 , 下面红色框框中应该不陌生了吧 , 嘿嘿( ̄▽ ̄)ノ

文章插图
然后我们上一篇中说的原理 , 去找到对应的命名空间处理器 , 下图所示;
所以我们就能知道命名空间处理器是DubboNamespaceHandler , 而且我们还能看到一些有意思的东西 , 由于dubbo已经被阿里给贡献到开源社区apache了 , 所以这里还保留了之前ali的命名空间 , 我们也能继续使用 , 嘿嘿
自己有兴趣的话 , 可以自己看看下图中的spring.schemas文件以及对应的xsd文件了 , 看看这个xsd文件就能知道dubbo的每个标签都有些什么属性了(我表示没有这么大的兴趣?乛?乛? , 你们自己看 , 哈哈哈)

文章插图
继续看看这个DubboNamespaceHandler中 , 下图所示 , 我们随便看一秒钟就能知道dubbo的配置文件中 , 跟dubbo相关的标签就是这么14个 , 而且解析每个标签的解析起都是DubboBeanDefinitionParser去解析成BeanDefinition对象 , 只不过每个BeanDefinition里面封装的对象不一样罢了

文章插图
这么多标签我们说哪一个呢?先说说我最感兴趣的一个标签<dubbo:service />, 大家知道这个标签是干啥的么 , 咱们后面慢慢看

文章插图
2.分布式服务基础
在说明<dubbo:service />标签的作用之前 , 我们先说说为什么要有远程调用?或者说dubbo在分布式架构中使用的位置 , 下面就用于给萌新科普一下 , 嘿嘿~
下图所示是我们看到的一个很经典的后端MVC三层结构, 这个应该都很熟悉了 , 而且这里后端的那三层都是在同一个机器上;

文章插图
【dubbo源码分析 dubbo服务暴露入口 dubbo源码分析5】那么问题来了 , 如果我要将service层放在另外一台机器上 , 你觉得Controller调用Service怎么做会比较好?下面有两种方式
方式一:我们在另外一台机器B上搭建一套MVC结构 , 注意 , 此时的机器B上的Controller中没有任何逻辑代码 , 就只是单纯的暴露一个机器B的入口 , 所以下面的步骤2可以直接使用Http请求去调用 , 比如使用Feign , HttpClient等http工具 , 聪明的人已经知道了 , 这特喵的就是springcloud的远程调用的方式嘛(╯-╰)/

文章插图
方式二 , 我们在机器B中 , 完全不需要Controller层 , 不就是两台机器通信么?大家知道java的网络编程吧 , 直接使用Socket建立网络通信就ok了;
我们现在使用dubbo就是用于实现下面的步骤2 , 更通俗的理解就是封装了java的网络编程(其实就是封装了netty框架) , 使得两台服务器之间可以进行远程调用 , 而不需要使用http请求的方式了;

文章插图
方式2优化: 但是由于我们的机器B可能有很多台 , 我们总不能在机器A中每次调用B机器的接口的时候 , 都要知道B的ip和端口吧?那多坑爹呀!
所以我们在机器B1和机器B2启动的时候 , 需要将机器B1和机器B2的接口信息(ip+端口+接口+方法+版本等信息)都放到注册中心(如下图的步骤1和步骤2) , 然后机器A从注册中心中将所有接口信息都给下载下(步骤3) , 然后决定去调用哪个机器上的服务(这里会涉及到负载均衡策略);
所以前端调用机器A , 机器A根据调用的接口就可以找到对应接口所在的机器是B2(步骤5) , 然后通过网络编程去连接机器B2就好了
在这里机器A就是服务消费者 , 机器B1和机器B2就是服务提供者;

文章插图
3.dubbo服务提供者暴露服务入口
在上面我们知道了 , dubbo其实就是解决一台机器去远程调用另外一台机器的接口 , 而且还将服务暴露到注册中心里 , 并提供负载均衡策略 的远程调用框架;
那么在dubbo中什么叫做服务呀?我们看看服务提供者的配置文件 , 下图所示一个<dubbo:service>标签就对应着一个服务接口 , 这个接口的信息需要暴露到注册中心的;
业余小知识:可以思考一下 , 下图中这个接口只会暴露到注册中心中去么?(肯定是暴露到注册中心中一份 , 也会暴露一份到当前所在机器的jvm中呀!为什么呢?因为也有可能当前机器中其他的服务会使用到这个demoService服务呀 , 同一台机器上就不必走注册中心 , 肯定直接走jvm会更快呀)
所以我们又可以知道暴露服务 , 可以分为本地暴露和远程暴露嘛!当然 , 我们主要看的是远程暴露吧 , 哈哈哈哈?乛?乛?

文章插图
下面我们就看看是怎么解析这个<dubbo:service>标签的过程
3.1.DubboNamespaceHandler
这里就是缓存了dubbo每一个标签所对应的一个解析器 , 当实际去解析<dubbo:service>标签的时候 , 就会从缓存中获取解析起 , new DubboBeanDefinitionParser(ServiceBean.class, true) , 然后调用这个解析起的parse方法
这里 , 继续科普一下 , 在spring中的BeanDefinition的作用:对xml文件中每一个bean的一个统一的抽象 , 简单来说就是首先会将所有解析的bean都变成BeanDefinition<T>对象 , 然后后面统一对所有的BeanDefinition进行实例化真正对象T , 可以看看这个老哥博客的图 , 很清晰 , 嘿嘿(╯-╰)/

文章插图
3.2 DubboBeanDefinitionParser的parse方法
这个方法很长 , 我们只看解析ServiceBean的地方
在看这个方法之前 , 继续强调一点 , 这里只是封装了BeanDefinition<ServiceBean>这种对象 , 在spring的机制中 , 后续才会真正的根据BeanDefinition去实例化出ServiceBean对象的(你要问spring中到底是哪里会实例化的 , 这个要自己去学习了 , 这里只是粗略的带过一下 , 这里重点还是dubbo)

文章插图

文章插图
看到这里 , 暂时不往后看了 , 后面一堆逻辑容易头晕 , 趁着头脑还很冷静 , 我们看点清神醒脑的
3.3.实例化ServiceBean对象
在spring的后续初始化流程中 , 会对所有BeanDefinition中封装的实际的对象进行实例化 , 其中一个就是ServcieBean , 我们看看ServiceBean是个什么东东( ̄o ̄) . z Z
这里请注意dubbo2.7.5之前和2.7.5之后的版本 , 变化很大很大 , 网上很多的ServcieBean的解析的博客都是2.7.5之前的 , 远古版本的了 , 我也在试着查了一些资料 , 尝试总结一下吧o(︶︿︶)o
3.3.1 先看看2.7.5之前
我把代码图和类的继承图都给出来 , 这里简单说一下spring中的原理 , 就不仔细看源码了
实现了InitializingBean和ApplicationListener接口的bean实例化的时候会做的事情 , 就是一个Bean首先在xml中进行配置 , 然后spring的容器在初始化的时候 , 会首先经过加载变成BeanDefinition对象 , 然后进行实例化BeanDefinition中实际的类型 , 这里实际的类型就是ServiceBean , 在创建了一个ServiceBean对象之后 , 设置属性值 , 然后就是对ServiceBean进行初始化操作:会判断是否实现了InitializingBean接口 , 实现了的话 , 就会执行afterPropertiesSet方法先初始化一下 , 然后会判断ServcieBean有没有初始化方法 , 就是配置文件中<bean>标签指定的init-method方法, 执行init-method方法之后 , 后续还有可能执行其他的各种对bean和容器的初始化操作 , 在经过了九九八十一难之后 , ioc容器和bean都会初始化完毕 , 此时ioc容器会判断所有实例化之后的bean有没有实现ApplicationListener接口 , 进而去执行每个bean的onApplicationEvent方法 , 此时ServiceBean就会去执行onApplicationEvent()方法 , 实际的去开始暴露自己服务

文章插图

文章插图
3.3.2 dubbo2.7.5的版本
我们看看代码和类图 , 很明显已经看不到那个EventListener接口了 , 那么我们就要看看这里是怎么暴露服务的

文章插图

文章插图
dubbo2.7.5提供了一个类DubboBootstrap类 , 这只是一个普通的监听器 , 但是里面有一个start方法 , 这里会调用exportServices()方法 , 然后就会去调用ServiceConfig的export()方法
(注意 , serviceBean是ServiceConfig的一个子类) , 其实就可以看做会调用我们ServiceBean的export()方法 , 进行服务的暴露

文章插图

文章插图
那么我们再看看从哪里调用的这个DubboBootstrap的start()方法 , 那么我们就知道所有流程了 , 下面再贴几段代码

文章插图

文章插图

文章插图

文章插图
我们理一下思路 , 其实spring的初始化流程跟2.7.5之前是一样的 , 只不过在最后ioc和bean初始化完成之后 , spring容器开始发布事件 , 在ioc容器中所有的实现了ApplicationListener接口的bean , 首先会执行OneTimeExecutionApplicationContextEventListener的onApplicationEvent()方法 , 在这个方法里面再执行DubboBootstrapApplicationListener的onApplicationContextEvent()方法 , 在这方法里面会执行当前类的onContextRefreshedEvent()方法 , 最后就是执行dubboBootstrap.start();开始暴露服务
4.总结
这篇博客其实就是说了我们从哪个角度去切入到dubbo框架中 , 说的东西很少 , 但是非常非常重要 , 只有找到了切入点之后 , 我们才可以痛快的继续往后走 , 不然学了一下就忘了 , 特喵的 , 以后每次都要看一遍 , 多麻烦呀!
只要跟着我这里往后走 , 以后想看哪里点哪里 , 就不用百度了 , 哈哈哈哈
其实本篇要说的最重要的就是dubbo的2.7.5版本 , 与之前相比暴露服务的方式做了很大的改变 , 使用到了一个DubboBootstarp启动器 , 在spring容器初始化完成之后 , 会发布对应的事件然后会带着dubbo的启动器也会跑起来 , 从中我们也可以看出来spring的扩展性是真的厉害 , dubbo也设计的非常巧妙 , 哈哈哈哈
下一篇真正的看看暴露服务的逻辑吧( ̄▽ ̄)ノ
--------------以上皆原创 , 给未来的自己留下一点学习的痕迹!--------
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
