重庆分公司,新征程启航

为企业提供网站建设、域名注册、服务器等服务

朝花夕拾---dubbo源码分析-创新互联

前言

该篇博客意在做dubbo启动调用流程做源码分析,采用先给出部分结论,然后推导出整个调用流程的过程

创新互联公司专业为企业提供李沧网站建设、李沧做网站、李沧网站设计、李沧网站制作等企业网站建设、网页设计与制作、李沧企业网站模板建站服务,十载李沧做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。一  服务发布

dubbo服务的每个标记了@service的类和在xml配置中带有标签,均会被解析成ServiceBean,服务发布的故事就从serviceBean这个类开始

首先看一下serviceBean的类继承关系:

从类继承图中,我们发现了几个重要的接口:

serviceConfig       这个是和dubbo服务发布相关的

ApplicationListener    spring的事件相关

InitializingBean       初始化相关

当然最重要的就是ApplicationListener的监听方法了:

以下是服务发布的几个重要路径:

ServiceBean#export();

ServiceConfig#doExport()

doExportUrlsFor1Protocol()

在doExportUrlsFor1Protocol这里就是服务发布的重点了

以上截图就是dubbo在做服务发布的核心代码了,这里dubbo使用了动态代理(SPI)+装饰器模式,完整的构造了一个Invoker和Exporter

DUBBO的SPI:ExtensionLoader  通过加载指定路径下,配置的key-value形式的类。同时还支持代理和增强(Wrapper + 装饰),有兴趣的同学可以认真研究一下dubbo的SPI机制,这里只做简单概括,比如里面2个最重要的代理对象:proxyFacotory,protocol,他们的源码分别截图如下:

proxyFactory:

protocol:

从以上截图不难发现:protocol和proxyFactory的处理逻辑大体类似:通过url获取指定参数,如果为空,就使用默认值:然后通过ExtensionLoader加载从url中获取的对象

首先看一下通过proxyFactory获取的Invoker对象:

想一下,为什么extName是javassist,获取到的ProxyFactory却是:StubProxyFactoryWrapper?按照之前说的SPI机制,应该获取的是:JavassistProxyFactory?

这是因为:在ExtensionLoader#createExtension时

cachedWrapperClasses的写入是在读取指定路径的文件时写入的,通过判断加载的类是否有,包含相同接口的构造器做判断的:

这里真正干活的还是:JavassistProxyFactory

所以,真正构建Invoker的代码如下:

其实就是构建了一个AbstractProxyInvoker,其中的Wrapper简单的理解成一个包装类即可(这就是dubbo动态生成类的方式,其实没有什么多大的技术问题,只是觉得就是装X而已),代码如下:

再来看看export过程:

同样的,extName是registry,实际的加载类是:ProtocolListenerWrapper

而ProtocolListenerWrapper里面包装的protocol是:ProtocolFilterWrapper,而ProtocolFilterWrapper里面包装的protocol是RegistryProtocol(真正干活的)

可以看下最终生成的Exporter的结构:

其中DubboExporter是在DubboProtocol类中构造的,还是和之前一样,通过装饰器,一层一层递进构造的:

至此,服务的发布已经完成,其中有些步骤跳跃可能稍微大一点,感兴趣的同学请自行本地调试 

二  服务调用

dubbo中每一个标记了@Reference域和在xml中配置了的元素,均会被解析成一个ReferenceBean

首先,看一下ReferenceBean的类关系:

其中FactoryBean就是spring的工厂Bean,和ServiceBean类似,ReferenceBean也继承一个Config类,如上,服务调用的故事就从ReferenceConfig的#get()开始

ReferenceBean#getObject()

  ReferenceConfig#get()

init();

相信使用过动态代理的同学都知道,使用动态代理的使用,通过代理对象,在自己的逻辑里面就可以"为所欲为"了。dubbo在服务调用的时候也是这么干的!

init方法就是创建代理的入口,方法比较长,咱们捡重点说,前面就是一些校验,判断,最主要的方法入口:

创建代理需要一个map,看看这个map里面的信息如下:

下面正式开启创建代理的过程,老规矩,忽略掉无关精要的代码,直接上干货:

这个refprotocol就是在前面截图的那个Protocol$Adaptive代码,这里咱们为了方便调试,直接把代码替换一下:

和服务发布过程一样,extName是registry,获取到的实例却是:ProtocolListenerWrapper(装饰器模式)

大概装饰层级就是:

ProtocolListenerWrapper

 ProtocolFilterWrapper

RegistryProtocol

在RegistryProtocol是真正干活的地方:

一路debug调试,最终返回到创建代理的代码入口:

在之前的服务发布过程中,我们已经帖出了proxyFactory的相关代码(dubbo这里做了动态加载,不利于调试,咱们做个替换)

替换后的代码如下:

现在将要进行真正的动态代理的创建过程:

和其他的Adaptive一样,真正干活的是JavassistProxyFactory,使用StubProxyFactoryWrapper做装饰

真正干活的是JavassistProxyFactory

看到这里,熟悉动态代理的同学已经很熟悉了。真正的执行逻辑就在InvokerInvocationHandler里面了,在这个handler里面是不是为所欲为呢?

截图如下:

由截图可知,在InvokerInvocationHandler里面真正调用就是使用invoker调用逻辑

当真正调用时,一路dubug

这个Invoker也是一个装饰器。咱们一步一步调试进入:

首先:MockClusterInvoker

真正的调用又委托给了:FailoverClusterInvoker

从以上代码注释中可以看出,FailoverClusterInvoker,通过负载均衡器选择"最优"的Invoker发起远程调用

这里选择了:RegistryDirectory$DeleteInvoker其实就是一个InvokerWrapper

真正干活的是ListenerInvokerWrapper

继续递进:调用ProtocolFilterWrapper

最终来到了ProtocolFilterWrapper的匿名内部类:

把调用过程委托给了filter调用链路,至此,Invoker的使命完成了。相信更深的调用逻辑,通过分析Filter就能找到答案了

三  FailOverClusterInvoker选择Invoker过程既FilterChain调用链的组装

在第二节中,有分析服务发布调用过程,最红是委托给了Filter调用。我们在分析的时候,有意的忽略掉了部分调用细节,只是为了更好的梳理出整个调用链路。下面就分析一下在负载均衡器选择Invoker的详细逻辑

故事的开始当然是从FailoverClusterInvoker的invoke开始,FailoverClusterInvoker没有自己实现invoke,其父类AbstractClusterInvoker实现了:

寻找Invoker的时候委托给了RegistryDirectory:

最终的Invoker寻找在RegistryDirectory里面维护的一个字段:methodInvokerMap里面查询即可

查询到全量的数据之后,就通过负载均衡器选择,完成Invoker的选择

那RegistryDirectory的methodInvokerMap又是在什么时候获得调用方法和Invoker的对应关系的呢?

通过跟踪字段的调用来源

最终确认: RegistryProtocol#doRefer时会调用到如上方法里面,生成method和Invokers的对应关系

以上,将服务发布,服务调用的过程做了较为粗略和完整的说明

四 结论证明

在前言部分有说过,先给出部分结论:

1 所有被标记了@service和使用标记的元素,均会被spring解析成ServiceBean

2 所有被标记了@Reference和使用的元素,均会被spring解析成ReferenceBean

这是怎么做到的呢?

在结合xml使用的时候,dubbo有引入DubboNamespaceHandler,该handler会解析相关的xml标签,完成如上功能:

而在springboot应用中,dubbo有引入:ServiceAnnotationBeanPostProcessor

该类是一个前置处理器,会扫描@service标记的类,通过构建BeanDefinitionBuilder完成ServiceBean的注册:

同样的:springboot应用中引入了ReferenceAnnotationBeanPostProcessor

ReferenceAnnotationBeanPostProcessor是一个后置处理器,在Bean初始化时会被调用,注入相应的代理类

创作不易,如果对你有帮助,请点赞+收藏!

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网页名称:朝花夕拾---dubbo源码分析-创新互联
链接地址:http://cqcxhl.cn/article/deoghc.html

其他资讯

在线咨询
服务热线
服务热线:028-86922220
TOP