架构图
不贴架构图的源码分析没有灵魂,所以,架构图在此。不过个人感觉,架构图的作用在于源码看的七七八八的时候,通过架构图将其串成一个整体,并理解其设计思路,官网网架构图如下:
Dubbo架构一共分了10层,各层均为单向依赖。
服务接口层(Service):该层是与实际业务逻辑相关,根据服务提供者和服务消费者的业务设计对应接口和实现。
配置层(Config):对外的配置接口,以ServiceConfig和ReferenceConfig为中心。
服务代理层(Proxy):服务接口的透明代理,生成服务的客户端Stub和服务端Skeleton,以ServiceProxy为中心,扩展接口为ProxyFactory。
服务注册层(Registry):封装服务地址的注册发现,以服务URL为中心,扩展接口为RegistryFactory、Registry和RegistryService,可能没有服务注册中心,此时服务提供者直接暴露服务。
集群层(Cluster):封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster、Directory、Router和LoadBalance。将多个服务提供者组合成一个服务提供者,实现对服务消费者透明,只需与一个服务提供者进行交互。
监控层(Monitor):RPC调用次数和调用时间监控,以Statistics为中心,扩展接口为MonitorFactory、Monitor和MonitorService。
远程调用层(Protocol):封装RPC调用,以Invocation和Result为中心,扩展接口为Protocol、Invoker和Exporter。Protocol是服务域,它是Invoker暴露和引用的主功能入口,负责Invoker的声明周期管理。Invoker是实体域,是Dubbo的核心模型,其他模型都向它靠拢或转换成它。它代表一个可执行体,可向它发起Invoke调用。
信息交换层(Exchange):封装请求响应模式,同步转异步,以Request和Response为中心,扩展接口为Exchanger、ExchangeChannel、ExchangeClient和ExchangeServer。
网络传输层(Transport):首相mina和netty为统一接口,以Message为中心,扩展接口为Channel、Transporter、Client、Server和Codec。
数据序列化层(Serialize):可复用一些工具,扩展接口为Serialization、ObjectInput、ObjectOutput和ThreadPool。
服务调用源码分析
在上文的ReferenceBean服务发现过程中的值,消费端的接口都会被封装成代理类,我们调用的接口的方法其实执行的是InvokerInvocationHandler#invoke方法。从这个方法开始,调用链还是有点长的:
InvokerInvocationHandler#invoke(Object, Method, Object[])
-> MockClusterInvoker#invoke(Invocation) //服务降级相关操作
-> AbstractClusterInvoker#invoke(Invocation) //列举可用服务以及初始化负载均衡对象
-> FailoverClusterInvoker#doInvoke(Invocation, List<Invoker<T>>, LoadBalance) //Failover模式的集群容错
-> ListenerInvokerWrapper#invoke(Invocation)
-> Filter#invoke(Invoker, Invocation) // 包含多个 Filter 调用
-> AsyncToSyncInvoker#invoker //异步转同步
-> AbstractInvoker#invoke(Invocation) // 设置上下文参数
-> DubboInvoker#doInvoke(Invocation) // 设置客户端以及发送请求
-> ReferenceCountExchangeClient#request(Object, int) // 记录该client使用次数
-> HeaderExchangeClient#request(Object, int) // 执行心跳任务和连接超时重连任务
-> HeaderExchangeChannel#request(Object, int) // 设置请求参数
-> AbstractPeer#send(Object) // 检查chaneel是否关闭
-> AbstractClient#send(Object, boolean) // 获取NettyChannel发送请求
-> NettyChannel#send(Object, boolean) // 发送请求,触发writeAndFlush事件在pipeline中传播
从InvokerInvocationHandler#invoke方法开始,代码实现如下:
对toString、hashCode、equals方法进行特殊处理,继续向下调用进入MockClusterInvoker#invoke方法如下:
主要处理Mock服务降级的调用,主要有没有mock(默认),强制mock降级,以及调用失败抛出RpcException后mock降级三种方式。此处为默认方式,下一步进入AbstractClusterInvoker#invoke方法,实现代码如下:
主要将RpcContext上下文中的attachment添加到Invocation中,然后初始化负载均衡类,如果是异步则需要添加自增ID,然后进入FailoverClusterInvoker#doinvoke方法,代码如下:
主要处理集群容错机制相关操作,根据重试次数循环调用,远程调用的时候会根据负载均衡策略获取对应的invoker,执行其invoke方法,这是会经过InvokerWrapper#invoke和ListenerInvokerWrapper#invoke,然后会调用ProtocolFilterWrapper构建的Fliter链,包括ConsumerContextFilter、FutureFilter、MonitorFilter等,下一步就会进入AsyncToSyncInvoker#invoke方法,实现如下:
根据其名称就可以看出,这个类的作用就是异步转同步,因为Netty是基于异步事件驱动的,读写均为异步,需要做同步处理的时候,就主动调用AsyncRpcResult#get方法阻塞等待异步执行结果。
然后接下来进入AbstractInvoker#invoke方法,代码如下:
添加信息到 RpcInvocation#attachment 变量中,添加完毕后,调用 doInvoke 执行后续的调用,此处是DubboInvoker#doInvoke方法,实现如下:
设置参数,然后根据是否需要返回值判断,然后开始进入Exchange层开始发送请求,一串流转之后进入HeaderExchangeChannel#request方法,实现代码如下:
构建request对象,创建DefaultFuture,交由NettyClient发送请求,然后流转进入AbstractClient#send方法,代码如下:
交由NettyChannel#send方法继续执行:
这里,终于看到了触发writeAndFlush事件,在pipeline中传播,接下来就进入了handler的处理过程,包括我们上文分析的编解码handler以及业务handler。
但到这里一次远程服务调用并没有真正的完成,还差服务端的请求响应,以及消费端异步写回响应结果,其具体分析在下一篇文章服务端请求响应与消费端异步写回
中详细介绍。