• dubbo源码分析8(服务消费者之生成代理对象)


      前面几篇博客,说了很多dubbo服务提供者相关的流程;

      复习一下:首先服务提供者去暴露服务接口数据到注册中心,然后本地启动netty服务端监听是否有消费者的请求,现在我们可以看看消费者端是怎么从注册中心获取指定的接口信息, 然后访问netty服务端,就行了;

      提前须知:要提前了解spring的ioc容器初始化的过程以及调用ioc容器的getBean的逻辑,这个不是我们的重点

    1 准备工作

      我们先大概看看服务消费者大概做了些什么事情,打开消费者端的demo,下图所示,首先是初始化spring的ioc容器,然后从容器中获取实例bean, 然后调用该bean的方法

      结合我们知道的spring的知识,我们就大胆的猜测一下,在spring的ioc初始化的过程中,会解析我们配置在xml文件中<dubbo:reference id="xxx" interface="xxx"/>,解析出来的对象放在ioc容器中,下图所示,很明显当前服务的BeanDefinition中封装的是ReferenceBean对象,ReferenceBean封装了该服务的信息;

      这里消费者端初始化ioc容器的时候,和服务提供者一样,都是在DubboBootstrap的start方法开始发车,这个start方法里面会调用exportServices()方法暴露服务和referServices()引用服务,因为一个服务既可以是服务提供者,同时也可以是服务消费者,这个不难理解吧!比如A->B->C, B服务对A来说是服务提供者, 对C来说是服务消费者

      然后就是spring的逻辑了,在从ioc获取对象(也就是调用getBean方法)的时候,会判断这个对象ReferenceBean有没有实现FactoryBean接口,有的话,就调用FactoryBean的getObject方法

      刚好我们去看看ReferenceBean类,巧了( ̄o ̄) . z Z,刚好实现了FactoryBean接口,于是就会调用下图的getObject()方法

     

      总结一下,服务消费者就干了三件事:

      (1)启动ioc容器进行初始化,初始化过程中对dubbo的配置文件进行解析

        (2)从ioc容器获取bean的时候,调用getBean方法的时候,会判断当前的Bean是否实现了FactoryBean接口,有的话,就调用getObject方法生成代理对象,并放入ioc容器中

      (3)调用代理对象的方法,这个方法内部封装了远程调用的细节,返回调用结果;

    2.生成代理对象

      这里默认大家都对spring的ioc容器的启动已经很熟悉了,就不再过多的描述,我们就看看是怎么生成代理对象的;

      我们就从ReferenceBean的getObject方法开始出发,连续截图三张,我们可以看到调用了父类的ReferenceConfig的get()方法, 再之后就是调用init()方法进行初始化操作

      这个init方法很长, 我们等下看看调用createProxy(xxx)方法的逻辑

     

      2.1 创建代理对象

        这个init方法百分之九十的代码都是设置参数到map里面,然后再根据这个map创建代理对象

      下面都是createProxy方法内部比较重要的部分,总结一下其实就是干了几件事,首先就是判断引用的服务是本地注册还是远程注册, 如果是远程注册就继续判断有几个注册中心,如果只有一个注册中心的话,就去那个注册中心获取服务数据转为一个invoker就好了;

      如果是多个注册中心,就将每个注册中心中的该服务信息多转为invoker, 再用cluster将多个invoker合并成一个统一的invoker;

      最终就是调用代理工厂proxyFactory将invoker生成代理对象;

     

     

     

      最终的根据代理工厂将invoker生成代理对象

     

      现在基本流程我们知道了,首先看看是否有多个注册中心,因为一个服务可以同时注册到多个注册中心,这里会从多个注册中心中获取相同名字的服务, 然后再将这些服务合并成一个invoker,然后就是根据最后生成的invoker生成代理类

      接下来我们继续看看REF_PROTOCOL.refer(xxx)生成invoker的逻辑,还有FROXY_FACTORY.getProxy(invoker)生成代理类,理解了这两个逻辑,就ok了;

      

      2.2 REF_PROTOCOL.refer(xxx)生成invoker

      由于现在只有一个注册中心,我们从这里进入开始看看怎么生成invoker的逻辑

      首先获取到注册中心实例,根据我们的消费者端的信息,去注册中心里创建consumer节点,然后接下来就是订阅providers、configurators、routers 等节点数据,只要是这几个节点有数据变化,就会通知到消费者端

     

      其实到这里就已经很清晰了, 不过在上图的第3步,就是用一个接口可能是集群部署的嘛,然后都注册到同一个注册中心中,我们需要将获取到的这个接口的多个服务提供者,然后又给聚合成一个invoker(其实这里的directory比较形象,中文意思是目录,这个目录下可能有多个服务提供者的呀)

      3.FROXY_FACTORY.getProxy(invoker)生成代理对象

      在上面我们已经从所有注册中心获取了所有实现了该接口的服务,最后合并成了一个invoker,然后就是根据这个invoker生成代理对象

      在getProxy()方法里面,其实就是判断当前服务接口是不是一个泛化接口(可以去了解一下dubbo的泛化,就是另外一种调用接口的方式而已,可以不提供服务接口),如果是的话,就做特殊处理,否则就把代理对象直接返回

      这里很明显就是直接返回代理对象

      当代理对象生成出来了之后,后续的就跟dubbo没啥关系了, 就是spring的内容,将生成的代理对象放到ioc容器中,并该接口的全名称对应起来,只要是下次我们再去获取这个实例的时候,就直接从ioc容器中获取了

      下图所示,可以看到是一个代理对象

      可以看到最终的ioc容器中已经有个这个代理对象了

     

      4.总结

      服务消费者的逻辑会比较多,现在首先会根据你要调用的这个接口,去多个注册中心看看,而且每个注册中心相同的一个服务A还有可能有多个,我们最终就多个服务A给拼接成一个invoker

      然后我们再使用代理工厂将这个invoker生成一个代理对象,并且和该服务接口名称对应起来放到spring的ioc容器中,下次再去获取这个接口的服务的时候,就能获取到这个代理对象了,这个代理对象中肯定是封装了netty远程调用的逻辑

      下一篇我们看看是怎么进行远程调用,怎么拿到接口调用的返回值

  • 相关阅读:
    1061. 判断题(15)
    1031. 查验身份证(15)
    1006. 换个格式输出整数 (15)
    1046. 划拳(15)
    1001. 害死人不偿命的(3n+1)猜想 (15)
    1021. 个位数统计 (15)
    1054. 求平均值 (20)
    写出这个数 (20)
    设计模式之中介者模式
    kill命令
  • 原文地址:https://www.cnblogs.com/wyq1995/p/15807675.html
Copyright © 2020-2023  润新知