10-Dubbo启动器DubboBootstrap添加注册中心配置信息RegistryConfig

10.1 简介

先贴个代码用来参考:

  1. DubboBootstrap bootstrap = DubboBootstrap.getInstance();
  2. bootstrap.application(new ApplicationConfig("dubbo-demo-api-provider"))
  3. .registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))
  4. .protocol(new ProtocolConfig(CommonConstants.DUBBO, -1))
  5. .service(service)
  6. .start()
  7. .await();

上个博客我们说了启动器ApplicationConfig对象的创建,启动器对象在启动之前是要初始化一些配置信息的,这里我们来看这一行代码注册中心配置信息:

  1. registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))

10.2 注册中心的配置相关

下面的配置来源于官网

属性对应URL参数类型是否必填缺省值作用描述兼容性
idstring可选配置关联注册中心引用BeanId,可以在<dubbo:service registry=””>或<dubbo:reference registry=””>中引用此ID1.0.16以上版本
addresshost:portstring必填服务发现注册中心服务器地址,如果地址没有端口缺省为9090,同一集群内的多个地址用逗号分隔,如:ip:port,ip:port,不同集群的注册中心,请配置多个dubbo:registry标签1.0.16以上版本
protocolstring可选dubbo服务发现注册中心地址协议,支持dubbo, multicast, zookeeper, redis, consul(2.7.1), sofa(2.7.2), etcd(2.7.2), nacos(2.7.2)等协议2.0.0以上版本
portint可选9090服务发现注册中心缺省端口,当address没有带端口时使用此端口做为缺省值2.0.0以上版本
usernamestring可选服务治理登录注册中心用户名,如果注册中心不需要验证可不填2.0.0以上版本
passwordstring可选服务治理登录注册中心密码,如果注册中心不需要验证可不填2.0.0以上版本
transportregistry.transporterstring可选netty性能调优网络传输方式,可选mina,netty2.0.0以上版本
timeoutregistry.timeoutint可选5000性能调优注册中心请求超时时间(毫秒)2.0.0以上版本
sessionregistry.sessionint可选60000性能调优注册中心会话超时时间(毫秒),用于检测提供者非正常断线后的脏数据,比如用心跳检测的实现,此时间就是心跳间隔,不同注册中心实现不一样。2.1.0以上版本
fileregistry.filestring可选服务治理使用文件缓存注册中心地址列表及服务提供者列表,应用重启时将基于此文件恢复,注意:两个注册中心不能使用同一文件存储2.0.0以上版本
waitregistry.waitint可选0性能调优停止时等待通知完成时间(毫秒)2.0.0以上版本
checkcheckboolean可选true服务治理注册中心不存在时,是否报错2.0.0以上版本
registerregisterboolean可选true服务治理是否向此注册中心注册服务,如果设为false,将只订阅,不注册2.0.5以上版本
subscribesubscribeboolean可选true服务治理是否向此注册中心订阅服务,如果设为false,将只注册,不订阅2.0.5以上版本
dynamicdynamicboolean可选true服务治理服务是否动态注册,如果设为false,注册后将显示为disable状态,需人工启用,并且服务提供者停止时,也不会自动取消注册,需人工禁用。2.0.5以上版本
groupgroupstring可选dubbo服务治理服务注册分组,跨组的服务不会相互影响,也无法相互调用,适用于环境隔离。2.0.5以上版本
simplifiedsimplifiedboolean可选false服务治理注册到注册中心的URL是否采用精简模式的(与低版本兼容)2.7.0以上版本
extra-keysextraKeysstring可选服务治理在simplified=true时,extraKeys允许你在默认参数外将额外的key放到URL中,格式:“interface,key1,key2”。2.7.0以上版本

同样官网提供的参数里面并未包含所有的属性 下面我就将其余的属性列举一下方便学习参考:

变量类型说明
serverString
clientString
clusterString影响流量在注册中心之间的分布,在订阅多个注册中心时很有用,可用选项:1。区域感知,特定类型的流量总是根据流量的来源进入一个注册表。
zoneString注册表所属的区域,通常用于隔离流量
parametersMap<String, String>自定义参数
useAsConfigCenterBoolean该地址是否用作配置中心
useAsMetadataCenterBoolean该地址是否用作远程元数据中心
acceptsString此注册表接受的rpc协议列表,例如“dubbo,rest”
preferredBoolean如果设置为true,则始终首先使用此注册表,这在订阅多个注册表时非常有用
weightInteger影响注册中心之间的流量分布,当订阅多个注册中心仅在未指定首选注册中心时才生效时,此功能非常有用。
registerModeString注册模式:实例级,接口级,所有
enableEmptyProtectionBoolean收到的空url地址列表和空保护被禁用,将清除当前可用地址

10.3 注册中心配置对象创建与添加

前面例子中调用的代码

  1. .registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))

首先我们要来看的是RegistryConfig类型的构造器

  1. public RegistryConfig(String address) {
  2. setAddress(address);
  3. }

继续看setAddress方法

  1. public void setAddress(String address) {
  2. //保存地址
  3. this.address = address;
  4. //下面是支持将参数在url地址后面 比如用户名,密码,协议,端口,这几个参数提前做解析放入成员变量中
  5. if (address != null) {
  6. try {
  7. //地址转Dubbo的URL对象 这个URL是Dubbo自行实现的URL封装信息的类型
  8. URL url = URL.valueOf(address);
  9. // Refactor since 2.7.8
  10. //值不存在时候更新属性,非常巧妙的代码 重构了多个if判断
  11. //第一个参数值不存在则调用第二个方法,第二个方法的参数为第三方方法
  12. updatePropertyIfAbsent(this::getUsername, this::setUsername, url.getUsername());
  13. updatePropertyIfAbsent(this::getPassword, this::setPassword, url.getPassword());
  14. updatePropertyIfAbsent(this::getProtocol, this::setProtocol, url.getProtocol());
  15. updatePropertyIfAbsent(this::getPort, this::setPort, url.getPort());
  16. //移除掉url中的backup自定义参数 (备份的注册中心地址)
  17. Map<String, String> params = url.getParameters();
  18. if (CollectionUtils.isNotEmptyMap(params)) {
  19. params.remove(BACKUP_KEY);
  20. }
  21. //将自定义参数存储到成员变量中
  22. updateParameters(params);
  23. } catch (Exception ignored) {
  24. }
  25. }
  26. }

然后再回过头来看DubboBootstrap的registry方法:

  1. public DubboBootstrap registry(RegistryConfig registryConfig) {
  2. //将applicationModel对象设置给注册中心配置对象
  3. registryConfig.setScopeModel(applicationModel);
  4. //将注册中心配置对象添加到配置管理器中
  5. configManager.addRegistry(registryConfig);
  6. return this;
  7. }

直接来看配置管理器configManager的添加注册中心配置addRegistry方法:

  1. public void addRegistry(RegistryConfig registryConfig) {
  2. addConfig(registryConfig);
  3. }

configManager 的addConfig方法:

  1. public final <T extends AbstractConfig> T addConfig(AbstractConfig config) {
  2. if (config == null) {
  3. return null;
  4. }
  5. // ignore MethodConfig
  6. //检查当前配置管理器支持管理的配置对象
  7. //目前支持的配置有ApplicationConfig,MonitorConfig,MetricsConfig,SslConfig,
  8. //ProtocolConfig,RegistryConfig,ConfigCenterConfig,MetadataReportConfig
  9. if (!isSupportConfigType(config.getClass())) {
  10. throw new IllegalArgumentException("Unsupported config type: " + config);
  11. }
  12. if (config.getScopeModel() != scopeModel) {
  13. config.setScopeModel(scopeModel);
  14. }
  15. //缓存中是否存在
  16. Map<String, AbstractConfig> configsMap = configsCache.computeIfAbsent(getTagName(config.getClass()), type -> new ConcurrentHashMap<>());
  17. //不是服务级接口配置则直接从缓存中读取到配置之后直接返回
  18. // fast check duplicated equivalent config before write lock
  19. if (!(config instanceof ReferenceConfigBase || config instanceof ServiceConfigBase)) {
  20. for (AbstractConfig value : configsMap.values()) {
  21. if (value.equals(config)) {
  22. return (T) value;
  23. }
  24. }
  25. }
  26. // lock by config type
  27. //添加配置
  28. synchronized (configsMap) {
  29. return (T) addIfAbsent(config, configsMap);
  30. }
  31. }

ConfigManager配置管理器的addIfAbsent方法:

  1. private <C extends AbstractConfig> C addIfAbsent(C config, Map<String, C> configsMap)
  2. throws IllegalStateException {
  3. //配置信息为空直接返回
  4. if (config == null || configsMap == null) {
  5. return config;
  6. }
  7. // find by value
  8. //根据配置规则判断,配置存在则返回
  9. Optional<C> prevConfig = findDuplicatedConfig(configsMap, config);
  10. if (prevConfig.isPresent()) {
  11. return prevConfig.get();
  12. }
  13. //生成配置key
  14. String key = config.getId();
  15. if (key == null) {
  16. do {
  17. // generate key if id is not set
  18. key = generateConfigId(config);
  19. } while (configsMap.containsKey(key));
  20. }
  21. //不相同的配置key重复则抛出异常
  22. C existedConfig = configsMap.get(key);
  23. if (existedConfig != null && !isEquals(existedConfig, config)) {
  24. String type = config.getClass().getSimpleName();
  25. logger.warn(String.format("Duplicate %s found, there already has one default %s or more than two %ss have the same id, " +
  26. "you can try to give each %s a different id, override previous config with later config. id: %s, prev: %s, later: %s",
  27. type, type, type, type, key, existedConfig, config));
  28. }
  29. // override existed config if any
  30. //将配置对象存入configsMap对象中,configsMap来源于configsCache
  31. configsMap.put(key, config);
  32. return config;
  33. }

技术咨询支持,可以扫描微信公众号进行回复咨询
在这里插入图片描述