阿里dubbo服务注册原理解析

1、spring如何加载生成dubbo对象

下面是一段provider的xml配置

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       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">

    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="demo-provider"/>
    
    <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181" />
    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880"/>
    <!-- 和本地bean一样实现服务 -->
    <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
</beans>

       在很多情况下,我们需要为系统提供可配置化支持,简单的做法可以直接基于Spring的标准Bean来配置,但配置较为复杂或者需要更多丰富控制的时候,会显得非常笨拙。一般的做法会用原生态的方式去解析定义好的xml文件,然后转化为配置对象,这种方式当然可以解决所有问题,但实现起来比较繁琐,特别是是在配置非常复杂的时候,解析工作是一个不得不考虑的负担。Spring提供了可扩展Schema的支持,这是一个不错的折中方案,完成一个自定义配置一般需要以下步骤:

 设计配置属性和JavaBean

  •  编写XSD文件
  • 编写NamespaceHandler和BeanDefinitionParser完成解析工作
  • 编写spring.handlers和spring.schemas串联起所有部件
  • 在Bean文件中应用

       同样的dubbo为了解决这个问题,起了一个叫dubbo-config-spring的模块。这个模块的下面的resources/META-INF文件下面有三个这样的文件 dubbo.xsd 、spring.handlers、spring.schemas   如下图

 所以我们知道dubbo是利用了Spring提供的可扩展Schema机制实现了dubbo的xml配置文件解析。

 我在网上找了一个相关的的例子:http://blog.csdn.net/cutesource/article/details/5864562。

      解决了spring解析dubbo配置xml的问题,下面就看spring怎么生成dubbo对象的。 看一下解析xml的DubboNamespaceHandler

public class DubboNamespaceHandler extends NamespaceHandlerSupport {
 
    static {
 
        Version.checkDuplicate(DubboNamespaceHandler.class);
 
    }
 
  
    public void init() {
        registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
 
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
 
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
 
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
 
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
 
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
 
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
 
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
 
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
 
        registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
 
    }
  
}

  从这里知道所有的dubbo的标签,都是统一由DubboBeanDefinitionParser来解析的,每一个标签都会统一解析成对应的Bean对象。dubbo定义了以下Bean 

com.alibaba.dubbo.config.ApplicationConfig
com.alibaba.dubbo.config.ConsumerConfig
com.alibaba.dubbo.config.MethodConfig
com.alibaba.dubbo.config.ModuleConfig
com.alibaba.dubbo.config.MonitorConfig
com.alibaba.dubbo.config.ProtocolConfig
com.alibaba.dubbo.config.ProviderConfig
com.alibaba.dubbo.config.ReferenceConfig
com.alibaba.dubbo.config.RegistryConfig
com.alibaba.dubbo.config.spring.ServiceBean

而<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>对应的Bean就是 ServiceBean 

// 接口类型
 
private String interfaceName;
 
private Class<?> interfaceClass;
 
// 接口实现类引用
 
private T ref;
 
// 服务名称
 
private String path;
 
// 方法配置

以上是ServiceBean里面的一些属性截图,  所以知道为什么要ref=demoService了吧

2、dubbo服务如何注册到注册中心

 

解决了spring加载生成dubbo对象的问题。接下来进入第二部分:服务注册,看下ServiceBean的定

public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware {
 
    private static final long serialVersionUID = 213195494150089726L;
 
    private static transient ApplicationContext SPRING_CONTEXT;
 
    private final transient Service service;
 
    private transient ApplicationContext applicationContext;
 
    private transient String beanName;
 
    private transient boolean supportedApplicationListener;
 
    public ServiceBean() {
        super();
        this.service = null;
    }
 
    public ServiceBean(Service service) {
        super(service);
        this.service = service;
    }
 
    public static ApplicationContext getSpringContext() {
        return SPRING_CONTEXT;
    }
 
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        SpringExtensionFactory.addApplicationContext(applicationContext);
        if (applicationContext != null) {
            SPRING_CONTEXT = applicationContext;
            try {
                Method method = applicationContext.getClass().getMethod("addApplicationListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1
                method.invoke(applicationContext, new Object[]{this});
                supportedApplicationListener = true;
            } catch (Throwable t) {
                if (applicationContext instanceof AbstractApplicationContext) {
                    try {
                        Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1
                        if (!method.isAccessible()) {
                            method.setAccessible(true);
                        }
                        method.invoke(applicationContext, new Object[]{this});
                        supportedApplicationListener = true;
                    } catch (Throwable t2) {
                    }
                }
            }
        }
    }
 
    public void setBeanName(String name) {
        this.beanName = name;
    }
 
    /**
     * Gets associated {@link Service}
     *
     * @return associated {@link Service}
     */
    public Service getService() {
        return service;
    }
 
    public void onApplicationEvent(ApplicationEvent event) {
        if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) {
            if (isDelay() && !isExported() && !isUnexported()) {
                if (logger.isInfoEnabled()) {
                    logger.info("The service ready on spring started. service: " + getInterface());
                }
                export();
            }
        }
    }
 
    private boolean isDelay() {
        Integer delay = getDelay();
        ProviderConfig provider = getProvider();
        if (delay == null && provider != null) {
            delay = provider.getDelay();
        }
        return supportedApplicationListener && (delay == null || delay == -1);
    }
 
    @SuppressWarnings({"unchecked", "deprecation"})
    public void afterPropertiesSet() throws Exception {
        if (getProvider() == null) {
            Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);
            if (providerConfigMap != null && providerConfigMap.size() > 0) {
                Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
                if ((protocolConfigMap == null || protocolConfigMap.size() == 0)
                        && providerConfigMap.size() > 1) { // 兼容旧版本
                    List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();
                    for (ProviderConfig config : providerConfigMap.values()) {
                        if (config.isDefault() != null && config.isDefault().booleanValue()) {
                            providerConfigs.add(config);
                        }
                    }
                    if (providerConfigs.size() > 0) {
                        setProviders(providerConfigs);
                    }
                } else {
                    ProviderConfig providerConfig = null;
                    for (ProviderConfig config : providerConfigMap.values()) {
                        if (config.isDefault() == null || config.isDefault().booleanValue()) {
                            if (providerConfig != null) {
                                throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config);
                            }
                            providerConfig = config;
                        }
                    }
                    if (providerConfig != null) {
                        setProvider(providerConfig);
                    }
                }
            }
        }
        if (getApplication() == null
                && (getProvider() == null || getProvider().getApplication() == null)) {
            Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
            if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
                ApplicationConfig applicationConfig = null;
                for (ApplicationConfig config : applicationConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (applicationConfig != null) {
                            throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);
                        }
                        applicationConfig = config;
                    }
                }
                if (applicationConfig != null) {
                    setApplication(applicationConfig);
                }
            }
        }
        if (getModule() == null
                && (getProvider() == null || getProvider().getModule() == null)) {
            Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
            if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
                ModuleConfig moduleConfig = null;
                for (ModuleConfig config : moduleConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (moduleConfig != null) {
                            throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);
                        }
                        moduleConfig = config;
                    }
                }
                if (moduleConfig != null) {
                    setModule(moduleConfig);
                }
            }
        }
        if ((getRegistries() == null || getRegistries().size() == 0)
                && (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().size() == 0)
                && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {
            Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
            if (registryConfigMap != null && registryConfigMap.size() > 0) {
                List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
                for (RegistryConfig config : registryConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        registryConfigs.add(config);
                    }
                }
                if (registryConfigs != null && registryConfigs.size() > 0) {
                    super.setRegistries(registryConfigs);
                }
            }
        }
        if (getMonitor() == null
                && (getProvider() == null || getProvider().getMonitor() == null)
                && (getApplication() == null || getApplication().getMonitor() == null)) {
            Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
            if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
                MonitorConfig monitorConfig = null;
                for (MonitorConfig config : monitorConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (monitorConfig != null) {
                            throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);
                        }
                        monitorConfig = config;
                    }
                }
                if (monitorConfig != null) {
                    setMonitor(monitorConfig);
                }
            }
        }
        if ((getProtocols() == null || getProtocols().size() == 0)
                && (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().size() == 0)) {
            Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
            if (protocolConfigMap != null && protocolConfigMap.size() > 0) {
                List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
                for (ProtocolConfig config : protocolConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        protocolConfigs.add(config);
                    }
                }
                if (protocolConfigs != null && protocolConfigs.size() > 0) {
                    super.setProtocols(protocolConfigs);
                }
            }
        }
        if (getPath() == null || getPath().length() == 0) {
            if (beanName != null && beanName.length() > 0
                    && getInterface() != null && getInterface().length() > 0
                    && beanName.startsWith(getInterface())) {
                setPath(beanName);
            }
        }
        if (!isDelay()) {
            export();
        }
    }
 
    public void destroy() throws Exception {
        unexport();
    }
 
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

  结合spring的生命周期管理我们知道了ServiceBean初始化完毕之后会调用一个afterPropertiesSet的方法。注意这个方法很重要!!! 因为这个方法里面调用了com.alibaba.dubbo.config.ServiceConfig#export这个方法。通过对这个方法进去对代码进行跟踪最终会跳到下面一段代码:

//如果配置不是local则暴露为远程服务.(配置为local,则表示只暴露本地服务)
 
if (!Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope)) {
 
    if (logger.isInfoEnabled()) {
 
        logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
 
    }
 
    if (registryURLs != null && registryURLs.size() > 0
 
            && url.getParameter("register", true)) {
 
        for (URL registryURL : registryURLs) {
 
            url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));
 
            URL monitorUrl = loadMonitor(registryURL);
 
            if (monitorUrl != null) {
 
                url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString());
 
            }
 
            if (logger.isInfoEnabled()) {
 
                logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
 
            }
 
            Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
 
  
 
            Exporter<?> exporter = protocol.export(invoker);
 
            exporters.add(exporter);
 
        }
 
    } else {
 
        Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
 
  
 
        Exporter<?> exporter = protocol.export(invoker);
 
        exporters.add(exporter);
 
    }
 
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

这一段就是dubbo实现服务注册的真正代码!!!!!!!其中最关键的两句就是

Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));

Exporter<?> exporter = protocol.export(invoker)

上面的代码可以用一张图片作一个简单化的描述.整个服务的暴露过程如下图所示

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

然后再补上一消费者调用提供者的图 

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

    所以终于知道了dubbo暴露出去其实是一个Exporter!!!!!。 至于Invoker和Exporter的介绍这里就暂时不做了,因为要解释的话要讲的东西实在太多了。

下面给出具体某一种协议的实现

  假设配的协议是dubbo,注册中心用的是zookeepr。那么代码的调用过程大致是这样:

1、调用JavassistProxyFactory 生成一个Invoker。 对应Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));

2、用com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol#export方法,进行一个服务的暴露

3、DubboProtocol#export 方法最终会调com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryFactory#createRegistr进行一个服务注册 这时zookeepr相应的目录下面就会有对应的内容.这时服务注册就算完成了!!!

     其实dubbo的服务注册还牵涉到其它很多东西,实现的代码也是很复杂,代码之间的调用层次非常的多,我在这里也只能做一个大概的描述。希望这篇文章对想了解dubbo的人有所帮助吧。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值