Dubbo系列(二)服务发布注册原理

前言

源码地址:dubbo

版本: dubbo-parent pom中的version为

2.7.12-SNAPSHOT

测试代码:dubbo-demo module。在application.properties中,加入了registry url如下

dubbo.registry.address=zookeeper://127.0.0.1:2181

在dubbo中一切都是基于interface而来,对provider,consumer都是。在代码层面上对应AbstractInterfaceConfig,而接口又是以方法粒度扩展对应AbstractMethodConfig。
从代码层次上来看

在这里插入图片描述

AbstractServiceConfig:与服务提供方有关

  • ServiceConfig -> 对应的spring bean为子类ServiceBean
  • ProviderConfig

AbstractReferenceConfig:与服务消费方有关

  • ReferenceConfig->对应的spring bean为子类ReferenceBean
  • ConsumerConfig

启动入口
DubboBootstrapApplicationListener :继承自 OnceApplicationContextEventListener,该监听器只触发一次容器事件监听的执行避免事件传播,适合用于容器初始化完成和关闭等,定义的order为最低优先级保证当容器完全初始完成后最后执行。

onContextRefreshedEvent((ContextRefreshedEvent) event);
onContextClosedEvent((ContextClosedEvent) event);

当spring容器初始化完成后,该监听器会监听到ContextRefreshedEvent事件并执行DubboBootstrap的start,其中包括初始化、暴露服务、引用服务等所有流程,本次主要分析服务暴露的部分。

initialize:负责与dubbo相关的服务初始化,例如startConfigCenter会使用之前存放了相关配置信息(ApplicationConfig,ConfigCenterConfig等)的ConfigManager,将合适configCenter作为DynamicConfiguration存到environment
在这里插入图片描述

服务发布

DubboBootstrapApplicationListener监听到容器启动事件ContextRefreshedEvent
调用DubboBootstrap的start,其中与服务发布有关的为以下几个流程

exportServices

负责发布扫描到的dubbo service提供者。
DubboBootstrap中由configManager负责收集跟dubbo相关的服务,注册,协议等信息,并在此时直接定位要发布服务ServiceConfig;
根据需要异步或同步发布服务(ExecutorRepository也是dubbo扩展加载类的一种,利用executor异步处理发布每个service的任务);
exportService(ServiceConfig sc):执行ServiceConfig的export,并缓存到Map<String, ServiceConfigBase<?>> exportedServices中

ServiceConfig export

发布检验

比如是否设置了export为false,需要delay等

doExport

主要功能为doExportUrls。这里采用zookeeper注册中心为例

// 构造registry相关信息
List<URL> registryURLs = ConfigValidationUtils.loadRegistries(this, true);

拿到的registry url例如:registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-annotation-provider&dubbo=2.0.2&id=org.apache.dubbo.config.RegistryConfig#0&pid=13300&registry=zookeeper&timestamp=1627216227129;
依次对配置的protocols解析得到的ProtocolConfig,得到该服务对应在注册中心上(这里为zk)的path,一般为接口全路径名例如org.apache.dubbo.demo.DemoService, 并添加到ServiceRepository缓存中;调用doExportUrlsFor1Protocol处理对应协议的发布。

doExportUrlsFor1Protocol

  1. 构造url所需要的参数信息:比如side(provider),application,interface,methods及运行时信息等
  2. 对GenericService的情况进行处理:非generic时,会通过Wrapper找到该接口下对应要暴露的方法等,生成第一个interface->Wrapper0类存在于Wrapper的缓存中
       if (ProtocolUtils.isGeneric(generic)) {
   
            map.put(GENERIC_KEY, generic);
            map.put(METHODS_KEY, ANY_VALUE);
        } else {
   
          ....
            String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
            if (methods.length == 0) {
   
                logger.warn("No method found in service interface " + interfaceClass.getName());
                map.put(METHODS_KEY, ANY_VALUE);
            } else {
   
                map.put(METHODS_KEY, StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
            }
        }
  1. 解析host和port:用于定位ip和端口被消费方调用
  2. 构造服务方URL:用于服务方在注册中心的地址,例如,dubbo://172.xx.xx.x:20880/org.apache.dubbo.demo.DemoService?anyhost=true&application=dubbo-demo-annotation-provider&bind.ip=172.xx.xx.x&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.apache.dubbo.demo.DemoService&methods=sayHello,sayHelloAsync&pid=13300&release=&service.name=ServiceBean:/org.apache.dubbo.demo.DemoService&side=provider&timestamp=1627219556526
  3. ConfiguratorFactory:提供SPI接口扩展处理url参数信息的api,Configurator getConfigurator(URL url)
  4. scope决定发布类型:由目前url中的scope参数判断如何发布,none则不发布,不是remote(null的情况也匹配)则exportLocal(这里将执行),再接着不是local(null的情况也匹配)则进行远程发布(这里也会执行);

对第六步中不同方式发布进行下一步分析

exportLocal

用local URL的方式通过Protocol$Adaptive发布

//ServiceConfig中默认初始化了protocol和proxyFactory自适应代理类
private static final Protocol PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();

//exportLocal中,这里实际执行StubProxyFactoryWrapper和InjvmProtocol的接口方法
Exporter<?> exporter = PROTOCOL.export(PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, local));

其中StubProxyFactoryWrapper是个包装类,里面包裹的真正实现是JavassistProxyFactory(因为ProxyFactory的扩展目录中有符合条件的包装类StubProxyFactoryWrapper对其进行自动封装),因此会真正执行Javasist的export&#

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值