Dubbo源码分析1

大步流星 2013-05-09

这是本人对于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后创建NIOServer完成服务的暴露

i.DubboProtocol.openServer(url);

ii.创建封装了Inoker,key的DubboExporter后,通过URL创建NIOServer,且缓存暴露的Exporter,防止重复暴露。另外,同一个JVM中相同协议的服务共享同一个Server,不同服务中只有accept、idleTimeout、threads、heartbeat参数的变化会引用Server中属性的变化,但同JVM中同协议的服务均是引用同一个Server,第一个服务暴露是创建Server,其他服务的暴露是Server最多只是重置个别参数。

k)协议层创建NIOServer,并缓存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=newInvokerDelegete<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.newDubboInvoker<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对象的创建和管理成本。

相关推荐