Dubbo源码分析:dubbo与spring融合

概述

  • Dubbo框架主要是用于分布式系统中服务之间的远程调用。而分布式系统中的每个服务一般为采用spring框架搭建,通过spring容器管理beans,通过spring mvc提供restful接口,在service层进行业务逻辑处理。而不管是服务消费者引用的bean,还是服务提供者需要对外提供服务、进行注册的bean,都需要一种机制来触发其进行初始化,生成JVM堆的一个对象实例,同时由spring容器管理,可以通过@Autowired进行注入,从而可以在运行时进行调用。
  • 在dubbo源码结构中,主要在dubbo-config模块进行服务建模。具体为在dubbo-config-api子模块对服务进行各粒度的建模,依次为应用、提供者、消费者、注册中心、服务模块、服务提供类和引用类、方法、方法参数;在dubbo-config-spring子模块将消费者配置引用的服务,提供者配置对外提供调用的服务分别融合到相应项目的spring容器中,从而可以在service层通过@Autowired的机制进行注入。
    Dubbo源码分析:dubbo与spring融合_第1张图片

配置解析规则定义

  1. 在dubbo.xsd定义dubbo相关标签
    Dubbo源码分析:dubbo与spring融合_第2张图片
  2. 在dubbo.schemas定义标签的位置location
    在这里插入图片描述
  3. dubbo标签处理器器配置:在spring.handlers中定义了dubbo的命名空间和标签处理器DubboNamespaceHandler的对应关系,即当遇到dubbo标签的时候,使用DubboNamespaceHandler进行处理,解析生成beanDefinition,其中DubboNamespaceHandler继承于NamespaceHandlerSupport。
    Dubbo源码分析:dubbo与spring融合_第3张图片
    Dubbo源码分析:dubbo与spring融合_第4张图片

解析配置文件并生成beanDefinition

在spring扫描和解析xml文件遇到dubbo标签的时候,会使用DubboNamespaceHandler进行标签处理。

  1. DubboNamespaceHandler:自定义了BubboBeanDefinitionParser,使用相应的解析器,解析配置文件的标签,并转换成相应的beanDefinition。
    Dubbo源码分析:dubbo与spring融合_第5张图片
    Dubbo源码分析:dubbo与spring融合_第6张图片
  2. 通过registerBeanDefinitionParser将标签名称和解析器的对应关系注册到NamespaceHandlerSupport中的parsers中,从而在spring扫描和解析xml文件遇到对应的dubbo标签时,会使用相应的DubboBeanDefinitionParser进行标签解析,生成beanDefinition。通过registerBeanDefinitionParser将标签名称和解析器的对应关系注册到NamespaceHandlerSupport中的parsers中,从而在spring扫描和解析xml文件遇到对应的dubbo标签时,会使用相应的DubboBeanDefinitionParser进行标签解析,生成beanDefinition。
    Dubbo源码分析:dubbo与spring融合_第7张图片
    如果是使用注解而不是配置文件,则使用AnnotationBeanDefinitionParser。
    Dubbo源码分析:dubbo与spring融合_第8张图片

服务提供者提供的服务Service:ServiceBean

Dubbo源码分析:dubbo与spring融合_第9张图片

  1. ServiceBean实现ApplicationListener接口,泛型参数为ContextRefreshedEvent,从而在spring容器启动或重启时会触发。
    Dubbo源码分析:dubbo与spring融合_第10张图片
  2. ServiceBean继承于ServiceConfig,调用ServiceConfig的export方法,该方法会产生该service的Invoker,即通过该Invoker调用serviceImpl的方法,其中invoker是从该service的具体实现代理ref获取:
    Dubbo源码分析:dubbo与spring融合_第11张图片
    包含setRef方法,通过ExtensionLoader注入。
    在这里插入图片描述
  3. 由之前的文章分析可知,export最终会调用RegistryProtocol的export方法完成服务导出,注册到注册中心,同时会调用doLocalExport,在提供者本地生成消费者请求处理invoker。具体为根据URL确定所使用的、对应与dubbo-rpc模块的具体rpc协议protocol,如DubboProtocol,调用protocol.export创建export对象和实际的监听URL和请求处理器,DubboProtocol请求处理器的远程通讯由dubbo-remoting模块实现,源码如下:
    在这里插入图片描述
    Dubbo源码分析:dubbo与spring融合_第12张图片
    其中invoker为2中,注册导出服务时创建的invoker。

服务消费者引用的服务Reference:ReferenceBean

Dubbo源码分析:dubbo与spring融合_第13张图片

  1. 在解析dubbo:reference时,会产生ReferenceBean的实例。ReferenceBean实现了spring的FactoryBean接口,故spring在注入bean时,在程序使用如@Autowired时,会调用getObject方法,获取对象实例,如果是singleton类,则放到spring单实例缓存池。
  2. ReferenceBean继承于ReferenceConfig,getObject调用ReferenceConfig的get方法,其中get为使用synchronized修饰,保证只初始化一次:
    Dubbo源码分析:dubbo与spring融合_第14张图片
    init方法底层实现核心源码如下:
    Dubbo源码分析:dubbo与spring融合_第15张图片
    其中map为该对象实例的属性和属性值,通过createProxy创建消费者调用的代理对象。createProxy的核心源码实现如下:
    (1)refprotocol:根据URL的protocol获取到dubbo-rpc模块的protocol实现,调用refprotocol.refer获取对应的消费者端的调用;通过这个代理来对服务提供者或者说服务端发起RPC请求;
    (2)cluster.join:如果包含多个注册中心,则调用cluster.join进行负载均衡获取一个调用;
    (3)proxyFactory.getProxy(invoker):获取最终的消费者调用代理,代理提供了一个模板,最终的调用逻辑是定义在对应的Invoker的doInvoke方法,如DubboInvoker,在doInvoker中再调用dubbo-remoting模块的client进行远程通讯。
    Dubbo源码分析:dubbo与spring融合_第16张图片

DubboBootstrap注册spring shutdownHook

这个是在dubbo被apache孵化后,加入的。包括注册spring shutdownhook和export Service,但是export Service目前没有具体实现,还是在注册ServiceBean创建bean实例时,export。

  1. 通过context-param的方式将dubbo引入到宿主应用中
    web-fragment.xml文件:相当于web.xml的一个小片段,通过合并这个文件到web.xml,从而在宿主应用启动时,初始化DubboApplicationContextInitializer。
    Dubbo源码分析:dubbo与spring融合_第17张图片

  2. 监听spring框架启动:在DubboApplicationContextInitializer初始化时,将DubboApplicationListener作为监听器,监听宿主应用的启动。
    Dubbo源码分析:dubbo与spring融合_第18张图片
    DubboApplicationListener监听宿主应用的启动和关闭,调用DubboBootstrap进行dubbo框架的启动和关闭。
    Dubbo源码分析:dubbo与spring融合_第19张图片

    /**

    • A bootstrap class to easily start and stop Dubbo via programmatic API.

    • The bootstrap class will be responsible to cleanup the resources during stop.
      */
      public class DubboBootstrap
      核心方法
      public void start() {
      if (registerShutdownHookOnStart) {
      registerShutdownHook();
      } else {
      // DubboShutdown hook has been registered in AbstractConfig,
      // we need to remove it explicitly
      removeShutdownHook();
      }
      for (ServiceConfig serviceConfig: serviceConfigList) {
      serviceConfig.export();
      }
      }

      public void stop() {
      for (ServiceConfig serviceConfig: serviceConfigList) {
      serviceConfig.unexport();
      }
      shutdownHook.destroyAll();
      if (registerShutdownHookOnStart) {
      removeShutdownHook();
      }
      }

你可能感兴趣的:(java,dubbo,spring,java,数据结构,大数据)