Dubbo篇:消费端远程服务调用源码分析



架构图


        不贴架构图的源码分析没有灵魂,所以,架构图在此。不过个人感觉,架构图的作用在于源码看的七七八八的时候,通过架构图将其串成一个整体,并理解其设计思路,官网网架构图如下:

在这里插入图片描述

        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>, 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方法,实现如下:

AsyncToSyncInvoker

        根据其名称就可以看出,这个类的作用就是异步转同步,因为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。

        但到这里一次远程服务调用并没有真正的完成,还差服务端的请求响应,以及消费端异步写回响应结果,其具体分析在下一篇文章服务端请求响应与消费端异步写回中详细介绍。

©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页