`
humn_chou
  • 浏览: 22580 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Dubbo源码分析1

阅读更多
这是本人对于Dubbo源码分析的系列一,没有说明Dubbo是什么,不清楚请先了解,此处只是为了给自己做个笔记,也给正在学习Dubbo的同学一些借鉴,后期会继续奉上所有关于Dubbo的逻辑分析,包括Dubbo简介、初始化与请求细节、注册中心、监控中心、治理中心等(由于Dubbo本身的文档已经非常详细了,这里只是重构)。

A. Dubbo初始化、请求处理过程:(此处不涉及非常细节处,均以dubbo协议为例)
一、 Dubbo提供者初始化过程分析:
a) Dubbo解析xml,初始化且暴露所有服务
b) 由服务配置类ServiceConfig进行初始化工作及服务暴露入口
i. ServiceConfig.export();
c) 服务可以多协议暴露
i. ServiceConfig.doExportUrls();
d) 在某个协议下暴露服务
i. ServiceConfig.doExportUrlsFor1Protocol();
e) 将服务实现类转化成invoker
i. proxyFactory.getInvoker(service,interface,url);
ii. 提供者端的invoker封装了服务实现类、URL、Type,状态均是只读,线程安全,是Dubbo中核心模型,Dubbo中的是实体域,其他所有模型都向它靠拢或转化成它,是一个可执行体,通过发起invoke来具体调用服务类,它可能是个本地实现类,也可能是个远程实现类,也可能是个集群实现invoker,由ProxyFactory产生,具体是AbstractProxyInvoker
f) 暴露封装服务的Invoker
i. Protocol.export(invoker);
ii. Protocol是Dubbo中的服务域,只在服务启用是加载且无状态,天生线程安全,它是实体域Invoker暴露和引用的主功能入口,它负责Invoker的生命周期管理,是Dubbo中远程服务调用层。Dubbo有多种协议支持,有dubbo、http、rmi、hessian、injvm、webService等,下面具体说明服务暴露的细节,包括服务的注册、订阅、暴露、过滤器、监听器的初始化,其中服务的暴露则为Dubbo中的一重点。
g) 注册中心协议集成,装饰真正暴露引用服务的协议,增强注册发布功能
i. RegistryProtocol.export(invoker);
ii. ServiceConfig中的protocol是被多层装饰的Protocol,是DubboProtocolRegistryProtocolProtocolListenerWrapperProtocolFilterWrapper(此处是以dubbo协议为例,还有HttpPtotocol、HessianProtocol、RmiProtocol),其中ProtocolFilterWrapper是负责初始化invoker所有的Filter、ProtocolListenerWrapper是负责初始化暴露或引用服务的监听器、RegistryProtocol是负责注册服务到注册中心与向注册中心订阅服务、DubboProtocol是负责服务的具体暴露与引用,且DubboProtocol也负责网络传输层、信息交换层的初始化及底层NIO框架的初始化
h) 注册中心协议处理invoker后交给具体协议进行服务暴露
i. RegistryProtocol.doLocalExport(invoker)
ii. RegistryProtocol对原始invoker做一些简单状态后交给具体协议暴露,协议不关系invoker如何生成,由上层传入。接下来就是协议对invoker的暴露,此步骤是Dubbo中的核心。
i) 协议层暴露服务前初始化过滤器与服务暴露引用的监听器
i. 此步骤由上面提到的ProtocolListenerWrapper、ProtocolFilterWrapper完成,它们是协议的装饰者,增强功能(装饰模式大量使用在Dubbo中)。
j) 协议暴露服务
ii. DubboProtocol.export();
iii. 进入远程调用层Protocol,此层封装了所有remote层逻辑,对上层透明,暴露服务大致可以分为两步,第一是将invoker转化成Exporter;第二是根据URL绑定IP与端口建立NIO框架的Server;此两步的联系是通过URL关联在一起,协议层缓存了所有暴露的服务,其中key是由group、serviceName、version、port组成,它们的组合具体一个暴露服务,当NIO客户端发起远程调用时,NIO服务端通过此key来决定具体调用执行哪个Exporter,即执行的Invoker,对于NIO框架的底层通信下面会有讲解。
j) 协议层创建Exporter后创建NIO Server完成服务的暴露
i. DubboProtocol.openServer(url);
ii. 创建封装了Inoker,key的DubboExporter后,通过URL创建NIO Server,且缓存暴露的Exporter,防止重复暴露。另外,同一个JVM中相同协议的服务共享同一个Server,不同服务中只有accept、idleTimeout、threads、heartbeat参数的变化会引用Server中属性的变化,但同JVM中同协议的服务均是引用同一个Server,第一个服务暴露是创建Server,其他服务的暴露是Server最多只是重置个别参数。


k) 协议层创建NIO Server,并缓存Server
i. DubboProtocol.createServer(url);
ii. Dubbo底层通信是通过支持异步、事件驱动的NIO网络编程框架,如:Netty、Mina、Grizzly,此框架是典型的Reactor模式使用,使得单个线程处理多个请求,且支持多请求并行执行,NIO接受请求处理流程是读取请求数据解码执行业务逻辑编码发送回应消息,Dubbo是对NIO框架的再次抽象封装,加入一些Dubbo需要的逻辑,通过抽象扩展Handler完成,如HeaderExchangerHandler完成请求-响应模式、同步转异步模式消息发送,AllChannelHandler通过线程池完成请求、响应、连接等并行执行,下面会详细介绍。
iii. Exchangers.bind(url,requestHanler);
iv. Exchangers是门面类,Exchanger的逻辑封装在里面,通过此FACADE调用Exchanger逻辑,Dubbo目前只有一个HeaderExanger实现。从协议层进入Exchanger标志着程序进入了remote层,此层有消息交换层、网络传输层。当协议层调用bind(url,requestHanler)方法并传入最原始的处理Handler时,接下来就是remote层的Server和Hanlder及其他参数初始化的过程。
v. HeaderExchanger.bind(url,requestHandler);

vi. 此处是消息交换层与网络传输层初始化的入口,且负责将初始化后的Server传回给协议层。处理流程大致是Dubbo一系列Handler初始化、Server初始化。Handler包装过程是 协议层传入的原始requestHandlerHeaderExchangerHandlerDecodeHandlerAllChannelHandlerHeartbeatHandlerMultiMessageHandlerNettyServer[NettyHandler、NettyCodecAdapter]HeaderExchanerServer,HeaderExchanerServer封装了最终的Server,返回给上层协议层,NettyHandler、NettyCodecAdapter是NIO框架的直接处理Handler,NIO框架接受到消息后,先由NettyCodecAdapter解码,再由NettyHandler处理具体业务逻辑,再由NettyCodecAdapter编码后发送,NettyServer是个很重要的类,它既是Server又是Handler,而HeaderExchangerServer只是Server,所有NettyServer参与的Handler的处理过程,MultiMessageHandler是多消息处理Handler、HeartbeatHandler是处理心跳事件的Handler、AllChannelHandler是消息派发器,负责将请求放入线程池,并行执行请求,且Dubbo有多种线程模型、DecodeHandler是编码解码Handler、HeaderExchangerHandler是信息交换Handler,将请求转化成请求-响应模式与同步转异步模式,地位非常重要、requestHandler最后执行的Handler,它会在协议层选择Excporter后选择Invoker,进而执行Filter与invoker,最终执行请求服务实现类方法。
其中NIO框架的通信管道Channel也被Dubbo封装了,Channel直接触发事件并执行Handler,有ChannelNettyChannelHeaderExchangerChannel,通信管道Channel在有客户端连接Server时触发创建并封装成NettyChannel,再由HeaderExchangerHandler创建HeaderExchangerChannel,负责请求-响应模式的处理,注意NettyChannel其实也是个Handler,而HeaderExchangerChannel只是个Channel,是Handler的类说明它也具体Handler特性。
另外,还初始化一些参数,有AllChannelHandler的线程池模型、NettyServer的codesc解码编码方式,timeout超时时间,connectTimeout连接超时时时间,accepts提供者最大接受连接数设置,ildeTimeout时间设置,此处的参数得到都是为了后期可能重置准备。还有消息的序列化与发序列化工作全在NettyCodecAdapter中发起完成。
至此,分析了Dubbo初始化remote层所有初始化流程,还有,对于Transporters也是个门面类,内部调用网络传输层的逻辑,如:NettyTransporter、MinaTransporter。
附上连接过程:(当有客户端连接Server时)
0.NettyHandler.connected()
1.NettyServer.connected()
2.MultiMessageHandler.connected()
3.HeartbeatHandler.connected()
4.AllChannelHandler.connected()
5.DecodeHandler.connected()
6.HaderExchangeHandler.connected()
7.requestHandler.connected()
8.执行服务的onconnect事件的监听方法
下面是Handler、Server、Channel的结构图:



l) 将初始化后的Server返回协议层
i. 创建好的Server返回,此Server对象很重,缓存
m) 协议层将暴露后的Exporter返回给注册中心协议层,最后返回给ServiceConfig进行缓存
i. 协议层成功返回Exporter给注册中心协议层,标志着服务暴露完毕,接下来是与注册中心的操作,逻辑上看,注册中心负责服务的注册与发现,所有提供者向注册中心注册服务,并订阅重载配置,所有消费者向注册中心注册服务,并订阅服务,消费者通过注册中心自动发现所有服务提供者,且本地缓存提供者类表,注册中心宕机也不影响消费者调用;程序上看,注册中心也是普通的RPC服务,所有消费者、提供者与注册中心都是长连接。Dubbo目前注册中心服务有MulticastRegistry、ZookeeperRegistry等,关于注册中心的详细介绍待后期奉上。
ii. RegistryProtocol.getRegistry();
iii. 得到具体注册中心服务且连接注册中心,此时提供者作为消费者引用注册中心核心服务RegistryService
iv. Registry.register(url);
v. 调用远端注册中心的register()方法进行服务注册,且若有消费者订阅此服务,则推送消息让消费者引用此服务,注册中心缓存了所有提供者注册的服务以供消费者发现。
vi. Registry.subscribe(url,listener);
vii. 提供者向注册中心订阅所有注册服务的覆盖配置,当注册中心有此服务的覆盖配置注册进来时,推送消息给提供者,让它重新暴露服务,这由管理页面完成。
viii. 返回暴露后的Exporter给上层ServiceConfig进行缓存,便于后期撤销暴露。
ix. 总结:Exporter的创建、Server的创建、服务的注册与订阅,这些逻辑都是分离的,它们是通过URL联系在一起的。一般情况下,同JVM同协议下的服务共享同一个Server,且消费端的引用这些服务的也可共享一个Client,从而实现多个服务共享同一个通道进行通信,且是基于长连接下,减少了通信的握手次数,高效率通信,另外,远程调用层与信息交换层及网络传输层是Dubbo的核心。
二、 Dubbo消费者初始化过程分析:
a) Dubbo解析xml,初始化所有注入的引用服务及init=true引用服务
b) 所有dubbo引用服务均由ReferenceConfig入口进行服务的引用
i. ReferenceConfig.get(); ReferenceConfig.init();
ii. 消费者最终的得到的是服务的代理,在创建代理前初始化所有配置信息,此过程是线程安全的。引用服务的大致过程是由远程调用创建消费者端Invoker,再由ReferenceConfig创建代理返回,此过程的核心是创建消费端的Invoker。在引用服务前,ReferenceConfig先需要判断是否是引用本地服务injvm、是否是点对点直连、是否是通过注册中心连接,判断之后进行最重要的一步:服务的引用。
c) 进入远程调用层进行服务的引用
i. Protocol.refer(interface,url);
ii. 此方法返回的是个集群invoker,若有多个提供者提供服务,Dubbo将多个服务Invoker伪装成一个集群Invoker,且这个集群Invoker内部的多个invoker,由Directory完成,Directory与List类似,但由不同,当提供者推送消息过来后,Directory可以动态变化,还可以通过Router路由提供者及LoadBalance根据负载均衡算法选中一个提供者,所以当上层进行Invoker调用时,会是:Cluster.invoke()Directory.list()Router.route()LoadBalance.select()invoke.invoke();另外,在invoker转成proxy时,Dubbo对代理也有装饰,如Stub,这个可以实现在真正调用invoker代理前可以做一些事情,类似AOP功能。上面是大致说明以下消费者引用服务的过程,下面详细说明。
d) 首先进入注册中心远程调用层RegistryProtocol,且它也经过了ProtocolFilterWrapper、ProtocolListenerWrapper装饰,功能增强
i. RegistryProtocol.refer();
ii. 同提供者相同,消费者也首先需要连接注册中心,即引用注册中心这个特殊的RPC服务,并通过注册中心进行服务的订阅与注册。然后判断引用是否是注册中心RegistryService服务,若是绕过注册中心与集群等直接返回刚得到注册中心服务即可,若不是,则说明是普通服务,则需要进入注册中心与集群下面的逻辑。在选择集群策略前,先需要判断引用服务是否需要合并不同实现的返回结果,及是否配置group="*" merger="true" (配置详细说明再说),若配置了,则选择默认的分组聚合集群策略,若没配置,则选择配置的集群策略cluster="failback"或默认策略。下面进入服务引用的重点逻辑分析。
e) 服务引用,且向上层返回
i. RegistryProtocol.doRefer(cluster,registry,type,url);
ii. 消费端引用服务主要逻辑部分,服务引用大致逻辑是组合url、type创建目录类Directory,此类非常重要,它的功能很复杂,可以看成是NotifyListener服务通知监听器、可以看成Protocol、Registry的聚合类、可以看成一个消费端的List,但它又不同于List,他可以随着注册中心的消息推送而动态变化服务的Invoker数,时刻监听着提供者的变化,典型观察者模式的使用,它封装了所有服务真正引用逻辑、覆盖配置、路由规则等逻辑,初始化时只需要向注册中心发起订阅请求,其他逻辑均是异步的处理,包括服务引用等,且对上层Cluster层是透明的,ResitryProtocol将多个Invoker伪装成一个Invoker返回给上层来转化成代理,上层甚至不知道这是个集群Invoker,在伪装成一个Invoker时,Cluster也被装饰了,增强了Mock功能,这个详细暂不在此处说明。顶层得到伪装后的Invoker,当调用时,会根据初始化时的集群策略、负载均衡策略、路由策略进行选择调用某个Invoker。下面看看Directory的初始化与服务异步引用的分析及集群的处理步骤。
f) 目录类Directory初始化、服务订阅、集群伪装
i. 在RegistryProtocol中会根据url、type、protocol、registry初始化Directory,Directory功能非常强大,此处暂不说明详细功能。订阅服务前,注册中心首先注册服务,便于后期的监控中心提取数据,通过Directory订阅服务directory.subscribe(url),当有服务提供时,注册中心会推送服务消息给消费者,消费者再进行服务的引用,此处暂不详细说明注册中心的处理逻辑。下面是Directory中的代码块
,接下来服务的引用与变更全部由Directory异步完成,集群策略会将Directory伪装成一个invoker, cluster.join(directory),此代码就是伪装逻辑,Dubbo有很多集群策略,可以配置切换,具体集群逻辑暂不属于这里,后期说明。RegistryProtocol再将伪装后的Invoker返回给上层ReferenceConfig用来创建代理,所以消费者端的对象引用的远程服务其实引用的都是个代理,真正逻辑只有在调用时触发,包括Stub、Proxy、Mock、Cluster、Router、LoadBalance、Filter、Invoker、NIO框架底层通信。
g) Directory服务引用、NIO框架初始化
i. 注册中心接收到消费端发送的订阅请求后,会根据提供者注册服务的列表,推送服务消息给消费者,此处的逻辑不同的注册中心实现逻辑不通,详细暂不说明,消费者端接受到注册中心发来的提供者列表后,进行服务的引用,触发Directory监听器的可以是订阅请求、覆盖策略消息、路由策略消息(后两者由管理页面设置),接下面就是服务的引用过程,这逻辑都隐藏在Directory中。
invoker = new InvokerDelegete<T>(protocol.refer(serviceType, url), url, providerUrl);
h) 真正进入远程调用层,进行服务的引用与NIO框架的初始化
i. DubboProtocol.refer(type,url);
ii. 同服务的暴露逻辑相同,服务的引用步骤也分为两步,一是消费端Invoker的创建,如DubboInvoker,而是NIO框架的Client创建,这两步骤虽然是也是分离的,但它们不是通过URL联系在一起的,而是Invoker聚合了Client,当调用Invoker时,底层实际上是调用Client逻辑进行底层通信。
iii. new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
iv. Invoker创建,可以看出Invoker聚合了Client,此Invoker对象很重,远程调用层进行了缓存invokers.add(invoker);。
v. getClients(url)
vi. 此代码负责NIO框架Client创建及初始化,和提供者初始化相似,消费者的初始化也基本上围绕着Client、Handler、Channel对象的创建与不断装饰的过程,不同的是消费者底层是与提供者Server建立连接,此过程在remote层下完成,remote层可分为消息交换层与网路传输层即Exchanger与Transporter层,还有,我们在说提供者初始化时,说过同个JVM中相同协议的服务共享一个Server,同样在消费者初始化时,引用同一个提供者的所有服务可以共享一个Client进行通信,这也就实现了Server-Client在同一个通道中进行通信,实现长连接的高效通信,但是在服务请求数据量比较大时或请求数比较多时,可以设置每服务每连接或每服务多连接可以提高通信效率,具体是通过消费者方connections=2设置连接数。所有消费者端Client有两种,一种是共享型Client,一种是创建型Client,当然共享型Client属于创建型Client一部分,下面具体说说这两种Client创建的细节,也是服务引用的重要细节。


vii. getSharedClient(url)
viii. 此为创建共享型Client,共享型Client是指消费者引用同一提供者的服务时,使用同一个Client来提高通信效率,所以对于消费者来说,它连接的每个提供者都需要创建一个创建型Client,其他来自相同提供者的服务引用即可共享此Client,关于创建型Client的创建下面再说。对于共享型Client虽然可以提高通信效率,但会带来一个问题,就是如果所有共享一个Client的服务中的某个服务close了Client会导致其他服务都不能继续通信,这是个安全性问题,Dubbo的解决方案是通过计数的方式来控制这个安全问题,并在共享Client真正关闭后创建一个懒加载的幽灵Client,以备特殊情况使用(此处不说非常细节)。


ix. initClient(url)
x. 此为创建创建型Client,也是消费者端服务引用最核心的地方,封装了服务引用中remote层初始化的所有逻辑,与提供者端类似,就是Client、Handler、Channel的创建与不断装饰的过程,在说Client创建细节前,先说说Client类型,与其他产品一样,Dubbo中也有懒加载的概念,即Client分为正常马上连接的Client与懒加载的Client,懒加载的Client是个Client代理,当消费者真正调用服务时,才会去初始化Client、Handler、Channel,也就是才会与Server建立连接。
xi. Client、Handler、Channel初始化
xii. 此步骤是服务引用的核心的核心,逻辑完全封装在Protocol远程调用层,对于上层是完全透明的。在进行创建前,Dubbo默认开启remote层的心跳机制与禁止BIO通信,心跳机制是提供者与消费者之间的心跳通信,主要是防止通信异常,如提供者宕机,消费者自动重连提供者。下面重点是服务引用即Client的创建,此过程完成由Directory发起,有关于Directory的细节,后期会专栏介绍此类。同提供者类似,服务引用无非也就是初始化信息交换层与网络传输层即Exchanger与Transporter,且分别由门面类Exchangers与Transporters发起,Transporter返回的Client再经过Exchanger封装装饰后完成初始化并返回给上层Protocol。


详细是:远程调用层Protocol传入原始Handler,后续将是此Handler不断装饰的过程,下面是Handler与Server初始化过程:requestHandlerHeaderExchangerHandlerDecodeHandlerAllChannelHandlerHeartbeatHandlerMultiMessageHandlerNettyClient[NettyHandler、NettyCodecAdapter]HeaderExchanerClient 此处remote最终返回包装了NettyClient的HeaderExchangerClient到Protocol层,与提供者相比,消费者有以下异同:
1. 初始化的大致逻辑相同
2. 提供者暴露服务是绑定IP,而消费者是与提供者建立连接
3. 与NettyServer相同,NettyClient也是个Handler
4. 与HeaderExchangerServer不同,HeaderExchangerClient也是个Channel,这点一定注意
其中各个Handler、Client与提供者那里基本类似,这里不重复说明它们的功能,对于底层无非就是NIO框架的初始化,与Server建立连接。前面也说过了,返回到protocol层的Client被封装成消费端的Invoker,再返回给重要的Directory,那里动态引用了该服务所有与提供者建立后的Invoker,而真正protocol返回给上层的Invoker是封转了Directory的集群伪装Invoker,当真正调用时,才会根据集群策略、路由策略、负载均衡策略从Directory选择一个Invoker进行调用即Client与Server进行通信,所以Directory在Dubbo占有非常重要的位置,它的功能很复杂。
下面再说说消费者发起的Channel的创建:
消费者的NIO框架初始化是有一步很重要,就是与提供者建立连接即Channel的创建,NIO框架采用的双向通讯的通道Channel,而Dubbo对Channel也做了封装,封装过程是ChannelNettyChannelHeaderExchangerChannel,还有一点非常重要,查看Dubbo源码可知,NettyChannel其实也是个Handler,而HeaderExchangerChannel只是个Channel。在消费者端发起连接时,提供者端与消费者端的NettyHandler将被触发,将执行一系列的Handler或Server逻辑,在NettyHandler触发连接时,执行channelConnected创建Channel,Dubbo对NIO的Channel进行了包装,实现创建NettyChannel,它封装了NIO的Channel与包装Handler的NettyClient,值得注意的所有的事件都由NIO的Channel触发,如:写事件、读事件、连接事件、断开连接事件、出现异常事件。在Handler执行到HeaderExchangerHandler时,创建HeaderExchangerChannel,并且封装从Handler创建并传下来的NettyChannel。其中HeaderExchangerClient构造中有下面这段代码:

HeaderExchangerClient也有个封装了NettyClient的HeaderExchangerChannel,注意这个,因为这是消费者发起请求是底层通信的入口。
下面给出Client与Channel结构图,Handler图上面已有:


总结:所有的初始化,都是为了消费者与提供者之间的通信做准备,下面请结合初始化过程,重点查看通信的过程。再说说,这里的服务引用过程全部隐藏在Directory中,对上层完全透明,只有注册中心触发Directory进而触发服务引用或变更,而上层来说,它接受到的是集群伪装后的Invoker,然后再将Invoker转成Proxy,所以Spring中引用的是一个代理,只有消费者发起调用时,才有一系列的集群、路由、负载均衡逻辑,主要调用逻辑请看下面。
补充:和提供者暴露服务有暴露监听器一样ExporterListener,消费者端有引用服务的监听器InvokerListener,在服务引用时执行。
三、 Dubbo消费者--提供者请求过程与响应过程:
a) 大致过程
i. 消费者发送请求提供者处理消费者接受请求
ii. 在提供者与消费者端都初始化完毕时,提供者对外暴露的是Expoter、消费者对外提供的是Proxy,接下来就是从Proxy的执行到Exporter执行的过程,其中Dubbo中的会话域Invocation承载着提供者与消费者端的消息传递,并在每个线程栈中使用。下面是大致处理逻辑:
----------------------------------1.消费者发起请求-------------------------------------------
1. testService.hello();//消费者端呈现层引用的远程服务,这其实就是个代理
2. testServiceSub.hello();//proxy代理被Sub包装了,增强Sub功能,类似AOP
3. testServiceProxy.hello();//消费者端Invoker代理
4. InvokerInvocationHandler.invoker();//由代理类执行的invocationHandler
5. MockClusterInvoker.invoke();//集群对集群Invoker进行的包装,Mock功能
6. ClusterInvoker.invoke();//执行集群伪装的Invoker
7. Directory.list();//查找伪装在集群后面的所有Invoker
8. Router.route();//通过路由规则策略从list中选择一些Invoker
9. LoadBalance.select();//通过负载均衡选策略选中一个Invoker执行
10. Filter.invoke();//执行所有消费者端Filter
11. Invoker.invoke();//执行消费者端的Invoker即DubboInvoker
12. HeaderExchangerClient.request();//信息交换Client执行请求,其中封装了NettyClient、HeaderExchangerChannel
13. HeaderExchangerChannel.request();//此类封装了NettyClient,信息交换通道创建Request执行请求,并创建DefaultFuture返回
14. NettyClient父类AbstractClient.send();//消费者端Client执行请求
15. NettyChannel.send();//Netty通道执行请求发送
16. Channel.write();//NIO框架通知执行写操作,并触发Handler
17. NettyHanlder.writeRequested();//执行NIO框架的顶级Handler
18. NettyCodecAdapter.encode();//执行NIO框架的编码逻辑,以下执行Handler
19. NettyClient父类AbstractPeer.send();//执行装饰了Handler的NettyCient
20. MultiMessageHandler.send();//多消息处理Handler
21. HeartbeatHandler.send();//心跳处理Handler
22. AllChannelHandler.send();//消息派发器Handler
23. DecodeHandler.send();//编码Handler
24. HeaderExchangerHandler.send();//信息交换Handler
25. requestHandler父类ChannelHandlerAdapter.send();//最后执行Handler,以上Handler的执行在消费者端是没有意义,因为Channel.write ()执行时,提供者端已经收到消息了,也正在处理了,详细逻辑后面再说,这里为了完整性才这样写(以上是消费者请求大致过程,下面是提供者接受请求后处理并响应消费者过程)。
------------------------------2.提供者处理并响应请求--------------------------------------
26. NettyCodecAdapter.messageReceived();//提供者通过NIO框架通信并接受到消费者发送的信息,当然,这里屏蔽了所有NIO框架的逻辑,也屏蔽了所有编码解码与序列化反序列化的逻辑
27. NettyHandler.messageReceived();//提供者端的NIO顶级Handler处理
28. NettyServer.received();//NIO框架的Server接受请求信息
29. MultiMessageHandler.received ();//多消息处理Handler
30. HeartbeatHandler.received ();//心跳处理Handler
31. AllChannelHandler.received ();//消息派发器Handler
32. DecodeHandler.received ();//编码Handler
33. HeaderExchangerHandler.received ();//信息交换Handler,请求-响应模式
34. requestHandler.reply();//执行与Exporter交接的最初Handler
35. getInvoker();//先得到提供者端的Exporter再得到相应的提供者端Invoker
36. Filter.invoke();//执行所有提供者端的Filter,所有附加逻辑均由此完成
37. AbstractInvoker.invoke();//执行封装了服务实现类的原始Invoker
38. testServiceImple.hello();//执行服务实现类逻辑
39. NettyChannel.send();//HeaderExchangerHandler得到执行结果Response再返回给消费者,此代码由HeaderExchangerHandler发起
40. Channel.write ();//NIO框架通知执行写操作,并触发Handler
41. NettyHanlder.writeRequested();//执行NIO框架的顶级Handler
42. NettyCodecAdapter.encode();//执行NIO框架的编码逻辑,以下执行Handler
43. NettyServer父类AbstractPeer.send();//执行装饰了Handler的NettyServer
44. MultiMessageHandler.send();//多消息处理Handler
45. HeartbeatHandler.send();//心跳处理Handler
46. AllChannelHandler.send();//消息派发器Handler
47. DecodeHandler.send();//编码Handler
48. HeaderExchangerHandler.send();//信息交换Handler
49. requestHandler父类ChannelHandlerAdapter.send();//最后执行Handler,以上Handler的执行在提供者端也是是没有意义,因为Channel.write ()执行时,消费者端已经收到响应消息了,也正在处理了,详细逻辑后面再说,这里为了完整性才这样写(以上是消费者请求与提供者接受请求并响应大致过程,下面是消费者接受到提供者响应后处理过程)。
----------------------------------3.消费者接受响应------------------------------------------
50. NettyCodecAdapter.messageReceived();//提供者通过NIO框架通信并接受提供者发送过来的响应
51. NettyHandler.messageReceived();//消费者端的NIO顶级Handler处理
52. NettyClient.received();//NIO框架的Client接受响应信息
53. MultiMessageHandler.received ();//多消息处理Handler
54. HeartbeatHandler.received ();//心跳处理Handler
55. AllChannelHandler.received ();//消息派发器Handler
56. DecodeHandler.received ();//编码Handler
57. HeaderExchangerHandler.received ();//信息交换Handler,请求-响应模式
58. DefaultFuture.received();//设置response到消费者请求的Future中,以供消费者通过DefaultFuture.get()取得提供者的响应,此为同步转异步重要一步,且请求超时也由DefaultFuture控制。
-----------------------------------4.阻塞或异步断点---------------------------------------
59. Filter.invoke();//消费者异步得到响应后,DubboInvoker继续执行,从而Filter继续执行,从而返回结果给消费者。
60. InvokerInvocationHandler.invoker();//执行invocationHandler后续代码
61. testServiceProxy.hello();//消费者端Invoker代理后续代码
62. testServiceSub.hello();//执行后续代码
63. testService.hello();//执行后续代码
64. 呈现结果给消费者客户端
总结:消费者端的DubboInvoker发起请求后,后续的逻辑可以说是异步的或是指定超时时间内阻塞的,直到得到响应结果后,继续执行DubboInvoker中逻辑。对于异步请求时,消费者得到Future,其余逻辑均是异步的。以上主要核心逻辑,对于附加功能,大部分由Filter增强完成。消费者还可以通过设置async、sent、return来调整处理逻辑,async指异步还是同步请求,sent指是否等待请求消息发出即阻塞等待是否成功发出请求、return指是否忽略返回值即但方向通信,一般异步时使用以减少Future对象的创建和管理成本。
3
0
分享到:
评论
4 楼 HadesJK 2015-07-15  
自己看了服务发布与引用过程,在看楼主写的,收获颇深。
3 楼 jackyhongvip 2014-01-01  
不错。
2 楼 windy0605 2013-07-15  
LZ讲讲 dubbo的rpc整体设计架构,调用过程
1 楼 liuc121 2013-05-09  
虽然看不懂,但是必须顶!

相关推荐

    dubbo源码分析系列

    dubbo源码分析系列.

    dubbo源码解析2

    dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.

    dubbo源码分析pdf.zip

    dubbodubbo源码分析系列 dubbo源码解析书籍大全这两本书

    dubbo源码解析

    dubbo源码解析,dubbo源码解析,dubbo源码解析,dubbo源码解析

    Dubbo 源码分析

    Dubbo 源码分析

    dubbo源码分析

    dubbo源码分析系列 知秋整理 原文博客:https://my.oschina.net/ywbrj042/home 更多精彩学习内容,请关注本人github 一 项目工程结构介绍 摘要: dubbo是目前国内最流行的分布式服务框架,已经俨然成为行业的标准...

    Dubbo源码分析

    Dubbo源码分析;模块说明;总体架构;图例说明;各层说明:关系说明:依赖关系;调用链;配置文件解析;配置文件覆盖顺序;暴露服务时序;dubbo的远程调用(NIO机制)以及序列化;RPC 通信过程;消费服务时序;

    dubbo的源码分析

    dubbo源码,方便大家的学习 深入学习dubbo协议 企业级应用

    Dubbo源码分析之SPI

    SPI 全称为 Service Provider Interface,是一种服务发现机制。

    Dubbo源码解析

    牛人写的dubbo源码解析,适合中高级软件开发工程师阅读

    dubbo源码分析系列1

    摘要:dubbo­rpc­api模块是dubbo最为核心的一个模块,它定义了dubbo作为一个rpc框架最核心的一些接口和抽象实现,因此掌握这些内容对于学习其它

    dubbo2.0源码解读

    dubbo2 源码解读 1. 源码阅读路径 2. dubbo诞生的背景 3. dubbo架构简介 4. helloworld例子 5. 源文件概述 6. 核心机制分析 7. 集群、容错

    Spring+mybatis+dubbo整合源代码及jar包

    此框架为Spring4.1.6+mybatis3.2.8+dubbo2.5.3的框架源码以及依赖的包

    Dubbo源码+jar包

    ubbo是一个分布式服务框架,以及SOA治理方案。其功能主要包括:高性能NIO通讯及多协议集成,服务动态寻址与路由,软负载均衡与容错,依赖分析与降级等。

    demo-dubbo:dubbo源码分析

    demo-dubbo:dubbo源码分析

Global site tag (gtag.js) - Google Analytics