Dubbo的应用会在启动时完成服务注册或订阅(不论是生产者,还是消费者)如下图所示。

Dubbo 服务暴露注册流程_ide

  • 图中小方块Protocol, Cluster, Proxy, Service, Container, Registry, Monitor代表层或模块,蓝色的表示与业务有交互,绿色的表示只对Dubbo内部交互。
  • 图中背景方块Consumer, Provider, Registry, Monitor代表部署逻辑拓普节点。
  • 图中蓝色虚线为初始化时调用,红色虚线为运行时异步调用,红色实线为运行时同步调用。
  • 图中只包含RPC的层,不包含Remoting的层,Remoting整体都隐含在Protocol中。

整个服务初始化的过程细节如下:

解析服务

配置信息

在配置文件中,所有dubbo的标签,都统一用DubboBeanDefinitionParser进行解析,基于一对一属性映射,将XML标签解析为Bean对象。

相关信息可以参考: Dubbo中对Spring配置标签扩展

以 dubbo-demo-provider 为例, 它的配置文件如下:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
   
    <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" />
   
    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" />
   
</beans>

com.alibaba.dubbo.demo.provider.DemoServiceImpl 是服务实现类。

com.alibaba.dubbo.demo.DemoService 是服务需要实现的接口。

配置文件的解析过程

  • 基于dubbo.jar内的META-INF/spring.handlers配置,Spring在遇到dubbo名称空间时,会回调DubboNamespaceHandler。
  • 所有dubbo的标签,都统一用DubboBeanDefinitionParser进行解析,基于一对一属性映射,将XML标签解析为Bean对象。

每个service方法的配置会解析成对应的 com.alibaba.dubbo.config.spring.ServiceBean<T> 类的实例。

具体请参考:Dubbo中对Spring配置标签扩展

 

配置文件对应的配置类的关系图如下:

 

Dubbo 服务暴露注册流程_spring_02

根据 Spring Bean 的生命周期(javascript:void(0))

在 afterPropertiesSet 后, 会调用到 ServiceConfig.export() 。

Dubbo 服务暴露注册流程_配置文件_03

生产者在ServiceConfig.export()或消费者在ReferenceConfig.get()初始化时,将Bean对象转换URL格式,所有Bean属性转成URL的参数。

Dubbo 服务暴露注册流程_配置文件_04

它的调用堆栈如下图:

Dubbo 服务暴露注册流程_ide_05

 

然后将URL传给Protocol扩展点,基于扩展点的Adaptive机制,根据URL的协议头,进行不同协议的服务暴露或引用。

Dubbo 服务暴露注册流程_spring_06

 Dubbo 服务暴露注册流程_spring_07

 

public interface Protocol {   
/**   
 * 暴露远程服务:<br>    
 * 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().setRemoteAddress();<br>    
 * 2. export()必须是幂等的,也就是暴露同一个URL的Invoker两次,和暴露一次没有区别。<br>    
 * 3. export()传入的Invoker由框架实现并传入,协议不需要关心。<br>    
 *     
 * @param <T> 服务的类型    
 * @param invoker 服务的执行体    
 * @return exporter 暴露服务的引用,用于取消暴露    
 * @throws RpcException 当暴露服务出错时抛出,比如端口已占用    
 */    
@Adaptive    
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;