0
点赞
收藏
分享

微信扫一扫

[Dubbo3.0.8源码解析系列]-17-Dubbo3应用级注册之服务提供者的双注册原理


目录

  • ​​17-Dubbo服务提供者的双注册原理​​
  • ​​17.1 简介​​
  • ​​17.2 双注册配置的读取​​
  • ​​17.2.1 注册中心地址作为元数据中心​​
  • ​​17.2.2 双注册模式配置​​
  • ​​17.3 双注册服务数据的注册​​
  • ​​17.4 双注册元数据信息的注册​​

17-Dubbo服务提供者的双注册原理

17.1 简介

上个博客《15-Dubbo的三大中心之元数据中心源码解析》​导出服务端的时候多次提到了元数据中心,注册信息的注册。
Dubbo3出来时间不太长,对于现在的用户来说大部分使用的仍旧是Dubbo2.x,
Dubbo3 比较有特色也是会直接使用到的功能就是应用级服务发现

  • 应用级服务发现
    从服务/接口粒度到应用粒度的升级,使得 Dubbo 在集群可伸缩性、连接异构微服务体系上更具优势。应用粒度能以更低的资源消耗支持超百万实例规模集群程; 实现与 Spring Cloud、Kubernetes Service 等异构微服务体系的互联互通。

对于直接使用Dubbo3的用户还好,可以仅仅开启应用级注册,但是对于Dubbo2.x的用户升级到Dubbo3的用户来说前期都是要开启双注册来慢慢迁移的,既注册传统的接口信息到注册中心,又注册应用信息到注册中心,同时注册应用与接口关系的元数据信息。
关于双注册与服务迁移的过程的使用可以参考官网:
​​​应用级地址发现迁移指南​​

关于官网提供者双注册的图我这里贴一下,方便了解:
[Dubbo3.0.8源码解析系列]-17-Dubbo3应用级注册之服务提供者的双注册原理_ide

17.2 双注册配置的读取

17.2.1 注册中心地址作为元数据中心

这个配置的解析过程在前面的博客介绍元数据中心的时候很详细的说了相关链接:15-Dubbo的三大中心之元数据中心源码解析

对应代码位于:DefaultApplicationDeployer类型的startMetadataCenter()方法

private void startMetadataCenter() {
//如果未配置元数据中心的地址等配置则使用注册中心的地址等配置做为元数据中心的配置
useRegistryAsMetadataCenterIfNecessary();
//...省略掉其他代码防止受到干扰
}

具体逻辑是这个方法:
useRegistryAsMetadataCenterIfNecessary

private void useRegistryAsMetadataCenterIfNecessary() {
//配置缓存中查询元数据配置
Collection<MetadataReportConfig> metadataConfigs = configManager.getMetadataConfigs();

//...省略掉空判断
//查询是否有注册中心设置了默认配置isDefault 设置为true的注册中心则为默认注册中心列表,如果没有注册中心设置为默认注册中心,则获取所有未设置默认配置的注册中心列表
List<RegistryConfig> defaultRegistries = configManager.getDefaultRegistries();
if (defaultRegistries.size() > 0) {
//多注册中心遍历
defaultRegistries
.stream()
//筛选符合条件的注册中心 (筛选逻辑就是查看是否有对应协议的扩展支持)
.filter(this::isUsedRegistryAsMetadataCenter)
//注册中心配置映射为元数据中心 映射就是获取需要的配置
.map(this::registryAsMetadataCenter)
//将元数据中心配置存储在配置缓存中方便后续使用
.forEach(metadataReportConfig -> {
//...省略掉具体的逻辑
});
}
}

关于元数据中心地址的获取,主要经过如下逻辑:

  • 查询:所有可用的默认注册中心列表
  • 遍历:多注册中心遍历
  • 筛选:选符合条件的注册中心 (筛选逻辑就是查看是否有对应协议的扩展支持)
  • 转化:注册中心配置RegistryConfig映射转换为元数据中心配置类型MetadataReportConfig

MetadataReportConfig 映射就是获取需要的配置。

最后会把查询到的元数据中心配置存储在配置缓存中方便后续使用。

17.2.2 双注册模式配置

双注册配置类型是这个

dubbo.application.register-mode=all

默认值为all代表应用级注册和接口级注册,当前在完全迁移到应用级注册之后可以将服务直接迁移到应用级配置上去。
配置值解释:

  • all 双注册
  • instance 应用级注册
  • interface 接口级注册

后面的代码如果想要看更详细的代码可以看博客《16-模块发布器发布服务全过程》 关于这个配置的使用我们详细来看下,在Dubbo服务注册时候会先通过此配置查询需要注册服务地址,具体代码位于ServiceConfig的doExportUrls()方法中:

private void doExportUrls() {
//省略掉前面的代码...
List<URL> registryURLs = ConfigValidationUtils.loadRegistries(this, true);
//省略掉后面的代码...
}

然后就是具体注册中心地址的获取过程我们看下:
ConfigValidationUtils的加载注册中心地址方法loadRegistries

public static List<URL> loadRegistries(AbstractInterfaceConfig interfaceConfig, boolean provider) {
// check && override if necessary
//省略掉前面的代码...
//这里会获取到一个接口配置注册地址例如:registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-api-provider&dubbo=2.0.2&pid=9008&registry=zookeeper&release=3.0.8&timestamp=1653703292768
List<RegistryConfig> registries = interfaceConfig.getRegistries();
//省略掉中间的的代码...
return genCompatibleRegistries(interfaceConfig.getScopeModel(), registryList, provider);
}

ConfigValidationUtils的双注册地址的获取genCompatibleRegistries方法.
前面代码获取到了一个注册中心地址列表例如:

registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-api-provider&dubbo=2.0.2&pid=9008&registry=zookeeper&release=3.0.8&timestamp=1653703292768

下面可以看下如果根据配置来转换为应用级注册地址+接口级注册地址

private static List<URL> genCompatibleRegistries(ScopeModel scopeModel, List<URL> registryList, boolean provider) {
List<URL> result = new ArrayList<>(registryList.size());
registryList.forEach(registryURL -> {
if (provider) {
// for registries enabled service discovery, automatically register interface compatible addresses.
String registerMode;
if (SERVICE_REGISTRY_PROTOCOL.equals(registryURL.getProtocol())) {
//为了更好理解这里简化掉服务发现注册地址配置的逻辑判断过程仅仅看当前例子提供的值走的逻辑
} else {
//双注册模式配置查询 对应参数为dubbo.application.register-mode 默认值为all
registerMode = registryURL.getParameter(REGISTER_MODE_KEY, ConfigurationUtils.getCachedDynamicProperty(scopeModel, DUBBO_REGISTER_MODE_DEFAULT_KEY, DEFAULT_REGISTER_MODE_ALL));
//如果用户配置了一个错误的注册模式配置则只走接口级配置 这里默认值为interface
if (!isValidRegisterMode(registerMode)) {
registerMode = DEFAULT_REGISTER_MODE_INTERFACE;
}
//这个逻辑是满足应用级注册就添加一个应用级注册的地址
if ((DEFAULT_REGISTER_MODE_INSTANCE.equalsIgnoreCase(registerMode) || DEFAULT_REGISTER_MODE_ALL.equalsIgnoreCase(registerMode))
&& registryNotExists(registryURL, registryList, SERVICE_REGISTRY_PROTOCOL)) {
URL serviceDiscoveryRegistryURL = URLBuilder.from(registryURL)
.setProtocol(SERVICE_REGISTRY_PROTOCOL)
.removeParameter(REGISTRY_TYPE_KEY)
.build();
result.add(serviceDiscoveryRegistryURL);
}
//这个逻辑是满足接口级注册配置就添加一个接口级注册地址
if (DEFAULT_REGISTER_MODE_INTERFACE.equalsIgnoreCase(registerMode) || DEFAULT_REGISTER_MODE_ALL.equalsIgnoreCase(registerMode)) {
result.add(registryURL);
}
}
//省略掉若干代码和括号

return result;
}

可以看到这里简化的配置比较容易理解了

  • 双注册模式配置查询 对应参数为dubbo.application.register-mode ,默认值为all
  • 如果用户配置了一个错误的注册模式配置则只走接口级配置 这里默认值为interface
  • 满足应用级注册就添加一个应用级注册的地址
  • 满足接口级注册配置就添加一个接口级注册地址

这个方法是根据服务注册模式来判断使用接口级注册地址还是应用级注册地址分别如下所示:
配置信息:
dubbo.application.register-mode
配置值:

  • interface
  • 接口级注册
  • instance
  • 应用级注册
  • all
  • 接口级别和应用级都注册

最终的注册地址配置如下:
接口级注册地址:

registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-api-provider&dubbo=2.0.2&pid=9008&registry=zookeeper&release=3.0.8&timestamp=1653703292768

应用级注册地址:

service-discovery-registry://8.131.79.126:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-api-provider&dubbo=2.0.2&pid=10275&registry=zookeeper&release=3.0.8&timestamp=1653704425920

17.3 双注册服务数据的注册

17.4 双注册元数据信息的注册

//todo 中午了先做饭吃了后面继续写

举报

相关推荐

0 条评论