如何更好地学习dubbo源代码(转)

很荣幸,作为这样一款业界使用率和好评率出众的RPC框架的维护者,今天这个文章主要是想帮助那些热爱开源的同学,更好的来研究dubbo的源代码。

一、Dubbo整体架构

1、Dubbo与Spring的整合 Dubbo在使用上可以做到非常简单,不管是Provider还是Consumer都可以通过Spring的配置文件进行配置,配置完之后,就可以像使用 spring bean一样进行服务暴露和调用了,完全看不到dubbo api的存在。这是因为dubbo使用了spring提供的可扩展Schema自定义配置支持。在spring配置文件中,可以像、这样进行配置。 META-INF下的spring.handlers文件中指定了dubbo的xml解析类:DubboNamespaceHandler。像前面的被解 析成ServiceConfig,被解析成ReferenceConfig等等。 2、jdk spi扩展 由于Dubbo是开源框架,必须要提供很多的可扩展点。Dubbo是通过扩展jdk spi机制来实现可扩展的。具体来说,就是在META-INF目录下,放置文件名为接口全称,文件中为key、value键值对,value为具体实现类 的全类名,key为标志值。由于dubbo使用了url总线的设计,即很多参数通过URL对象来传递,在实际中,具体要用到哪个值,可以通过url中的参 数值来指定。 Dubbo对spi的扩展是通过ExtensionLoader来实现的,查看ExtensionLoader的源码,可以看到Dubbo对jdk spi做了三个方面的扩展:

(1)jdk spi仅仅通过接口类名获取所有实现,而ExtensionLoader则通过接口类名和key值获取一个实现;

(2)Adaptive实现,就是生成一个代理类,这样就可以根据实际调用时的一些参数动态决定要调用的类了。

(3)自动包装实现,这种实现的类一般是自动激活的,常用于包装类,比如Protocol的两个实现类:ProtocolFilterWrapper、ProtocolListenerWrapper。 3、url总线设计 Dubbo为了使得各层解耦,采用了url总线的设计。我们通常的设计会把层与层之间的交互参数做成Model,这样层与层之间沟通成本比较大,扩展起来也比较麻烦。因此,Dubbo把各层之间的通信都采用url的形式。比如,注册中心启动时,参数的url为: registry://0.0.0.0:9090?codec=registry&transporter=netty 这就表示当前是注册中心,绑定到所有ip,端口是9090,解析器类型是registry,使用的底层网络通信框架是netty。

二、Dubbo启动过程

Dubbo分为注册中心、服务提供者(provider)、服务消费者(consumer)三个部分。 1、注册中心启动过程 注册中心的启动过程,主要看两个类:RegistrySynchronizer、RegistryReceiver,两个类的初始化方法都是start。 RegistrySynchronizer的start方法:

(1)把所有配置信息load到内存;

(2)把当前注册中心信息保存到数据库;

(3)启动5个定时器。 5个定时器的功能是: (1)AutoRedirectTask,自动重定向定时器。默认1小时运行1次。如果当前注册中心的连接数高于平均值的1.2倍,则将多出来的连接数重定向到其他注册中心上,以达到注册中心集群的连接数均衡。 (2)DirtyCheckTask,脏数据检查定时器。作用是:分别检查缓存provider、数据库provider、缓存consumer、数据库 consumer的数据,清除脏数据;清理不存活的provider和consumer数据;对于缓存中的存在的provider或consumer而数 据库不存在,重新注册和订阅。 (3)ChangedClearTask,changes变更表的定时清理任务。作用是读取changes表,清除过期数据。 (4)AlivedCheckTask,注册中心存活状态定时检查,会定时更新registries表的expire字段,用以判断注册中心的存活状态。如果有新的注册中心,发送同步消息,将当前所有注册中心的地址通知到所有客户端。 (5)ChangedCheckTask,变更检查定时器。检查changes表的变更,检查类型包括:参数覆盖变更、路由变更、服务消费者变更、权重变更、负载均衡变更。 RegistryReceiver的start方法:启动注册中心服务。默认使用netty框架,绑定本机的9090端口。最后启动服务的过程是在NettyServer来完成的。接收消息时,抛开dubbo协议的解码器,调用类的顺序是

NettyHandler-》NettyServer-》MultiMessageHandler-》HeartbeatHandler-》AllDispatcher-》DecodeHandler-》HeaderExchangeHandler-》RegistryReceiver-》RegistryValidator-》RegistryFailover-》RegistryExecutor。

2、provider启动过程 provider的启动过程是从ServiceConfig的export方法开始进行的,具体步骤是: (1)进行本地jvm的暴露,不开放任何端口,以提供injvm这种形式的调用,这种调用只是本地调用,不涉及进程间通信。 (2)调用RegistryProtocol的export。 (3)调用DubboProtocol的export,默认开启20880端口,用以提供接收consumer的远程调用服务。 (4)通过新建RemoteRegistry来建立与注册中心的连接。 (5)将服务地址注册到注册中心。 (6)去注册中心订阅自己的服务。 3、consumer启动过程 consumer的启动过程是通过ReferenceConfig的get方法进行的,具体步骤是: (1)通过新建RemoteRegistry来建立与注册中心的连接。 (2)新建RegistryDirectory并向注册中心订阅服务,RegistryDirectory用以维护注册中心获取的服务相关信息。 (3)创建代理类,发起consumer远程调用时,实际调用的是InvokerInvocationHandler。

三、实际调用过程 consumer端发起调用时,实际调用经过的类是: 1、consumer:

InvokerInvocationHandler-》MockClusterInvoker(如果配置了Mock,则直接调用本地Mock类)-》FailoverClusterInvoker(负载均衡,容错机制,默认在发生错误的情况下,进行两次重试)-》RegistryDirectory$InvokerDelegete-》ConsumerContextFilter-》FutureFilter->DubboInvoker

2、provider:

NettyServer-》MultiMessageHandler-》HeartbeatHandler-》AllDispatcher-》DecodeHandler-》HeaderExchangeHandler-》DubboProtocol.requestHandler-》EchoFilter-》ClassLoaderFilter-》GenericFilter-》ContextFilter-》ExceptionFilter-》TimeoutFilter-》MonitorFilter-》TraceFilter-》实际service。

四、Dubbo使用的设计模式 1、工厂模式 ServiceConfig中有个字段,代码是这样的:

privatestaticfinalProtocolprotocol=ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

Dubbo里有很多这种代码。这也是一种工厂模式,只是实现类的获取采用了jdk spi的机制。这么实现的优点是可扩展性强,想要扩展实现,只需要在classpath下增加个文件就可以了,代码零侵入。另外,像上面的 Adaptive实现,可以做到调用时动态决定调用哪个实现,但是由于这种实现采用了动态代理,会造成代码调试比较麻烦,需要分析出实际调用的实现类。 2、装饰器模式 Dubbo在启动和调用阶段都大量使用了装饰器模式。以Provider提供的调用链为例,具体的调用链代码是在 ProtocolFilterWrapper的buildInvokerChain完成的,具体是将注解中含有group=provider的 Filter实现,按照order排序,最后的调用顺序是

EchoFilter-》ClassLoaderFilter-》GenericFilter-》ContextFilter-》ExceptionFilter-》TimeoutFilter-》MonitorFilter-》TraceFilter。

更确切地说,这里是装饰器和责任链模式的混合使用。例如,EchoFilter的作用是判断是否是回声测试请求,是的话直接返回内容,这是一种责任 链的体现。而像ClassLoaderFilter则只是在主功能上添加了功能,更改当前线程的ClassLoader,这是典型的装饰器模式。 3、观察者模式 Dubbo的provider启动时,需要与注册中心交互,先注册自己的服务,再订阅自己的服务,订阅时,采用了观察者模式,开启一个listener。 注册中心会每5秒定时检查是否有服务更新,如果有更新,向该服务的提供者发送一个notify消息,provider接受到notify消息后,即运行 NotifyListener的notify方法,执行监听器方法。 4、动态代理模式 Dubbo扩展jdk spi的类ExtensionLoader的Adaptive实现是典型的动态代理实现。Dubbo需要灵活地控制实现类,即在调用阶段动态地根据参数决 定调用哪个实现类,所以采用先生成代理类的方法,能够做到灵活的调用。生成代理类的代码是ExtensionLoader的 createAdaptiveExtensionClassCode方法。代理类的主要逻辑是,获取URL参数中指定参数的值作为获取实现类的key。

时间: 2024-11-06 03:50:42

如何更好地学习dubbo源代码(转)的相关文章

如何在工作中更好的学习(二)

欢迎关注我的微信公众号:软件测试经验与教训 前言 去年写过一篇文章<如何在工作中更好的学习>,是从员工的角度谈如何在工作中学习提升.今天这篇文章,是写给管理者.从内容来看,本文更应该叫<如何引导下属自我充实,提升工作表现?>. 也许你有过这样的烦恼: 下属工作能力差,难以胜任工作,组织了很多培训,却收效甚微,甚至出于好心的培训最后引来下属的反感. 花了大量人力物力培养起来的人,却离职去了其他公司,你开始怀疑培训到底是否有必要. 下属没有学习主动性,没有上进心,整个团队只有你在操心.

Live555学习之一 源代码编译

Live555 是一个为流媒体提供解决方案的跨平台的C++开源项目,它实现了对标准流媒体传输协议如RTP/RTCP.RTSP.SIP等的支持.Live555实现了对多种音视频编码格式的音视频数据的流化.接收和处理等支持,包括MPEG.H.263+.DV.JPEG视频和多种音频编码.同时由于良好的设计,Live555非常容易扩展对其他格式的支持.目前,Live555已经被用于多款播放器的流媒体播放功能的实现,如VLC(VideoLan).MPlayer. 从今天开始我们将一起学习live555源码

室内设计和平面设计,哪个更适合女生学习?

室内设计和平面设计哪个更适合女生学习?哪个比较有前途?关于这个问题,小编的回答是这个没有一定的标准,还是要根据你自身的能力和各方面情况来选择适合自己的.个人兴趣是学习和工作的源动力.总得来说,学习这两个专业的女生并不少,关键是你喜欢什么擅长什么. 那到底室内设计和平面设计哪个更适合女生学习呢?哪个比较有前途呢?在了解这些问题前,小编觉得大家有必要了解一下,什么是平面设计?什么是室内设计?那接下来小编为大家一一解答. [揭秘]60秒看你自己适不适合当平面设计师:http://www.tianhus

如何更好地学习在线视频课程?

如何更好地学习在线视频课程? ?Lander Zhang 专注外企按需IT运维服务,IT Helpdesk 实战培训践行者博客:https://blog.51cto.com/lander 51CTO讲师首页:https://edu.51cto.com/lecturer/733218.html轻松进外企:IT Helpdesk工程师实战自学之路:博文介绍:https://blog.51cto.com/lander/2413018视频课程专题系列:https://edu.51cto.com/topi

树莓派学习笔记—— 源代码方式安装opencv

0.前言 本文介绍如何在树莓派中通过编译源代码的方式安装opencv,并通过一个简单的例子说明如何使用opencv. 更多内容请参考--[树莓派学习笔记--索引博文] 1.下载若干依赖项     在开始安装之前,最好更新树莓派软件源.如果更新时间太长,请参考博文修改软件源网络地址--[树莓派学习笔记--修改树莓派软件源] sudo apt-get update 请依次安装以下依赖项,这些必须安装的依赖项来自于opencv官网的说明,在多数debian系统中都可以采用这种方式进行安装.其实在树莓派

深入学习 DUBBO

1.什么是 RPC 协议? RPC 的全称是 Remote Procedure Call 是一种进程间通信方式.它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节.即程序员无论是调用本地的还是远程的,本质上编写的调用代码基本相同. 参考资料: 深入浅出 RPC - 浅出篇 - 瞬息之间- 博客频道 - CSDN.NET 2.为什么要使用 RPC 协议? 1. 简单:RPC 概念的语义十分清晰和简单,这样建立分布式计算就更容易. 2.

如何才能更好的学习易语言呢,常见的技巧分享

在我们刚学习易语言时,常常会遇到这样或是那样的问题,是我们真的不会吗?我个人认为,大部分并不是我们不会,而是我们没有用心去看.去体会.对于大部份的易友来说,学易语言用易语言,最主要的一点就是易语言入门非常容易,全中文编程.即时的帮助.简单明了的知识库文档及例程还有论坛共大家交流学习心德等.这些都为易友们在最大的成度上降低了学习的难度.但正是因为这些,也使我们在心里上放松了学习的态度,都认为太容易了,看一遍就会了.个别的易友没学几天就想做一个或是几个应用软件,这个想法是好的,但就现在所学到的知识,

为什么相比芯片,我们更在意深度学习框架的中国化?

这两天美国宣布对中兴进行封锁,可谓在科技圈掀起了从上到下的一股龙卷风. 4月16日美国商务部发布命令,禁止美国企业向中兴通讯销售元器件,时间长达7年.假如这一纸禁令真正生效,意味着中兴通讯旗下全产业链所依靠的芯片等核心元件失去获取渠道,基本意味着庞大的中兴通讯将面临无法继续经营的最坏可能. 中兴通讯股价随之快速下跌,已相当于两个跌停板,其美国供应商的股价在"禁令"发布后也遭遇不同程度的下跌. 19日,中国商务部新闻发言人高峰在新闻发布会上表示,美方行径引起了市场对于美国贸易和投资环境的

学习dubbo(四): 启动时检查

说明 Dubbo缺省会在启动时检查依赖的服务是否可用不可用时会抛出异常阻止Spring初始化完成以便上线时能及早发现问 题默认check=true. 注意 如果你的Spring容器是懒加载的或者通过API编程延迟引用服务请关闭check否则服务临时不可用时会抛出异常拿到 null引用如果check=false总是会返回引用当服务恢复时能自动连上.