Dubbo3 源码解读-宋小生-9:Dubbo启动器DubboBootstrap添加应用程序的配置信息ApplicationConfig

简介: > Dubbo3 已经全面取代 HSF2 成为阿里的下一代服务框架,2022 双十一基于 Dubbo3 首次实现了关键业务不停推、不降级的全面用户体验提升,从技术上,大幅提高研发与运维效率的同时地址推送等关键资源利用率提升超 40%,基于三位一体的开源中间件体系打造了阿里在云上的单元化最佳实践和统一标准,同时将规模化实践经验与技术创新贡献开源社区,极大的推动了开源技术与标准的发展。> 本文是
Dubbo3 已经全面取代 HSF2 成为阿里的下一代服务框架,2022 双十一基于 Dubbo3 首次实现了关键业务不停推、不降级的全面用户体验提升,从技术上,大幅提高研发与运维效率的同时地址推送等关键资源利用率提升超 40%,基于三位一体的开源中间件体系打造了阿里在云上的单元化最佳实践和统一标准,同时将规模化实践经验与技术创新贡献开源社区,极大的推动了开源技术与标准的发展。

本文是 Dubbo 社区贡献者宋小生基于 Dubbo3 3.0.8 版本撰写的源码解析博客,在 Dubbo3 开源&内部技术栈统一的情况下,期望能对集团内的开发者了解 Dubbo3 背后的实现原理有所帮助。可点此查看 博客原文

本篇是宋小生系列 9/30 篇。同时,由 Dubbo3 团队领导的源码解读系列也正在进行中,感兴趣的同学可加入钉钉群了解详情: 28165003194

9.1 简介

先贴个代码用来参考:

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

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

bootstrap.application(new ApplicationConfig("dubbo-demo-api-provider"))

9.2 应用程序ApplicationConfig的配置信息

ApplicationConfig的构造器比较简单就是为他的成员变量name赋值来标识这个应用程序的名字
下面我们直接参考下官网的配置表格:

属性 对应URL参数 类型 是否必填 缺省值 作用 描述 兼容性
name application string 必填 服务治理 当前应用名称,用于注册中心计算应用间依赖关系,注意:消费者和提供者应用名不要一样,此参数不是匹配条件,你当前项目叫什么名字就填什么,和提供者消费者角色无关,比如:kylin应用调用了morgan应用的服务,则kylin项目配成kylin,morgan项目配成morgan,可能kylin也提供其它服务给别人使用,但kylin项目永远配成kylin,这样注册中心将显示kylin依赖于morgan 1.0.16以上版本
version application.version string 可选 服务治理 当前应用的版本 2.2.0以上版本
owner owner string 可选 服务治理 应用负责人,用于服务治理,请填写负责人公司邮箱前缀 2.0.5以上版本
organization organization string 可选 服务治理 组织名称(BU或部门),用于注册中心区分服务来源,此配置项建议不要使用autoconfig,直接写死在配置中,比如china,intl,itu,crm,asc,dw,aliexpress等 2.0.0以上版本
architecture architecture string 可选 服务治理 用于服务分层对应的架构。如,intl、china。不同的架构使用不同的分层。 2.0.7以上版本
environment environment string 可选 服务治理 应用环境,如:develop/test/product,不同环境使用不同的缺省值,以及作为只用于开发测试功能的限制条件 2.0.0以上版本
compiler compiler string 可选 javassist 性能优化 Java字节码编译器,用于动态类的生成,可选:jdk或javassist 2.1.0以上版本
logger logger string 可选 slf4j 性能优化 日志输出方式,可选:slf4j,jcl,log4j,log4j2,jdk 2.2.0以上版本
metadata-type metadata-type String 可选 local 服务治理 metadata 传递方式,是以 Provider 视角而言的,Consumer 侧配置无效,可选值有: remote - Provider 把 metadata 放到远端注册中心,Consumer 从注册中心获取 local - Provider 把 metadata 放在本地,Consumer 从 Provider 处直接获取 2.7.6以上版本

官网的配置很详细了上面有一些属性是值得注意的比如这个name,compiler,logger,metadata-type 我们可能要多看下默认值是什么,方便我们在使用过程中遇到问题的排查

常用的属性参考官网的表格已经足够了,不过上面的属性不是列举了所有的属性,后续应该官方文档回更新:
我这里把缺失的一些属性列举出来:

变量 类型 说明
registries List 应用级注册中心列表
registryIds String 注册中心id列表
monitor MonitorConfig 应用级监控配置
dumpDirectory String 保存线程转储的目录
qosEnable Boolean 是否启用qos
qosHost String 要侦听的qos主机地址
qosPort Integer 要侦听的qos端口
qosAcceptForeignIp Boolean qos是否接收外部IP
parameters Map<String, String> 自定义参数
shutwait String 应用程序关闭时间 赋值属性的时候会想系统属性dubbo.service.shutdown.wait里面存一份
hostname String 主机名
registerConsumer Boolean 用于控制是否将实例注册到注册表。仅当实例是纯消费者时才设置为“false”。
repository String 没找到哪里用了
enableFileCache Boolean 是否开启本地文件缓存
protocol String 此应用程序的首选协议(名称)适用于难以确定哪个是首选协议的地方
metadataServiceProtocol String 用于点对点的元数据传输的协议
metadataServicePort Integer 元数据服务端口号,用于服务发现
livenessProbe String Liveness 存活探针 用于设置qos中探测器的扩展
readinessProbe String Readiness 就绪探针
startupProbe String Startup 启动探针
registerMode String 注册模式,实例级,接口集,所有
enableEmptyProtection Boolean 接收到的空url地址列表和空保护被禁用,将清除当前可用地址

这里我们先来简单了解下这个实体类型的基本配置,直接看配置可能不太好理解,后面我们讲到每个配置的时候可以回来参考一下

应用程序配置对象添加到启动器中的配置管理器中

了解了配置信息再回过头来看下这个配置信息如何存放到启动器里面的:

我们的Demo调用代码如下:

 DubboBootstrap bootstrap = DubboBootstrap.getInstance();
 bootstrap.application(new ApplicationConfig("dubbo-demo-api-provider"))

DubboBootstrap的application方法设置一个应用程序配置ApplicationConfig对象

 public DubboBootstrap application(ApplicationConfig applicationConfig) {
         //将启动器构造器中初始化的默认应用程序模型对象传递给配置对象
        applicationConfig.setScopeModel(applicationModel);
        //将配置信息添加到配置管理器中
        configManager.setApplication(applicationConfig);
        return this;
    }

ConfigManager配置管理器的setApplication方法

  @DisableInject
    public void setApplication(ApplicationConfig application) {
        addConfig(application);
    }

ConfigManager配置管理器的addConfig方法

public final <T extends AbstractConfig> T addConfig(AbstractConfig config) {
        
        if (config == null) {
            return null;
        }
        // ignore MethodConfig
        //检查当前配置管理器支持管理的配置对象
        //目前支持的配置有ApplicationConfig,MonitorConfig,MetricsConfig,SslConfig,
        //ProtocolConfig,RegistryConfig,ConfigCenterConfig,MetadataReportConfig
        if (!isSupportConfigType(config.getClass())) {
            throw new IllegalArgumentException("Unsupported config type: " + config);
        }
        
        if (config.getScopeModel() != scopeModel) {
            config.setScopeModel(scopeModel);
        }
        
        //缓存中是否存在
        Map<String, AbstractConfig> configsMap = configsCache.computeIfAbsent(getTagName(config.getClass()), type -> new ConcurrentHashMap<>());

        // fast check duplicated equivalent config before write lock
        //不是服务级配置则直接从缓存中读取到配置之后直接返回
        if (!(config instanceof ReferenceConfigBase || config instanceof ServiceConfigBase)) {
            for (AbstractConfig value : configsMap.values()) {
                if (value.equals(config)) {
                    return (T) value;
                }
            }
        }

        // lock by config type
        //添加配置
        synchronized (configsMap) {
            return (T) addIfAbsent(config, configsMap);
        }
    }

ConfigManager配置管理器的addIfAbsent方法:

private <C extends AbstractConfig> C addIfAbsent(C config, Map<String, C> configsMap)
        throws IllegalStateException {
        //配置信息为空直接返回
        if (config == null || configsMap == null) {
            return config;
        }

        // find by value
        //根据配置规则判断,配置存在则返回
        Optional<C> prevConfig = findDuplicatedConfig(configsMap, config);
        if (prevConfig.isPresent()) {
            return prevConfig.get();
        }
        
        //生成配置key
        String key = config.getId();
        if (key == null) {
            do {
                // generate key if id is not set
                key = generateConfigId(config);
            } while (configsMap.containsKey(key));
        }

        //不相同的配置key重复则抛出异常
        C existedConfig = configsMap.get(key);
        if (existedConfig != null && !isEquals(existedConfig, config)) {
            String type = config.getClass().getSimpleName();
            logger.warn(String.format("Duplicate %s found, there already has one default %s or more than two %ss have the same id, " +
                    "you can try to give each %s a different id, override previous config with later config. id: %s, prev: %s, later: %s",
                type, type, type, type, key, existedConfig, config));
        }

        // override existed config if any
        //将配置对象存入configsMap对象中,configsMap来源于configsCache
        configsMap.put(key, config);
        return config;
    }

原文: <<Dubbo启动器DubboBootstrap添加应用程序的配置信息ApplicationConfig>>

目录
相关文章
|
2月前
|
Dubbo Cloud Native 网络协议
【Dubbo3技术专题】「服务架构体系」第一章之Dubbo3新特性要点之RPC协议分析介绍
【Dubbo3技术专题】「服务架构体系」第一章之Dubbo3新特性要点之RPC协议分析介绍
40 1
|
2月前
|
XML Dubbo Java
【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南(二)
【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南
55 0
|
2月前
|
XML Cloud Native Dubbo
【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南(一)
【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南
55 1
|
2月前
|
Kubernetes Dubbo 应用服务中间件
【Dubbo3终极特性】「流量治理体系」一文教你如何搭建Dubbo3的控制台服务Dubbo-Admin
【Dubbo3终极特性】「流量治理体系」一文教你如何搭建Dubbo3的控制台服务Dubbo-Admin
74 0
|
2月前
|
Dubbo Cloud Native 应用服务中间件
【Dubbo3 终极特性】「云原生三中心架构」带你探索 Dubbo3 体系下的配置中心和元数据中心、注册中心的原理及开发实战(中)
【Dubbo3 终极特性】「云原生三中心架构」带你探索 Dubbo3 体系下的配置中心和元数据中心、注册中心的原理及开发实战(中)
28 1
|
2月前
|
Cloud Native Dubbo 应用服务中间件
【Dubbo3技术专题】拥有新时代的通信协议,引领云原生迈向更高的舞台 | 解密Dubbo3是如何从微服务升华到云原生领域
【Dubbo3技术专题】拥有新时代的通信协议,引领云原生迈向更高的舞台 | 解密Dubbo3是如何从微服务升华到云原生领域
43 1
|
2月前
|
XML Dubbo Java
【Dubbo3技术专题】回顾Dubbo2.x的技术原理和功能实现及源码分析(温故而知新)(二)
【Dubbo3技术专题】回顾Dubbo2.x的技术原理和功能实现及源码分析(温故而知新)
22 2
|
18天前
|
Dubbo Java 应用服务中间件
微服务学习 | Springboot整合Dubbo+Nacos实现RPC调用
微服务学习 | Springboot整合Dubbo+Nacos实现RPC调用
|
6月前
|
负载均衡 Dubbo 应用服务中间件
微服务技术系列教程(31) - Dubbo-原理及负载均衡分析
微服务技术系列教程(31) - Dubbo-原理及负载均衡分析
56 0
|
5月前
|
Dubbo Java 应用服务中间件
阿里巴巴资深架构师深度解析微服务架构设计之SpringCloud+Dubbo
软件架构是一个包含各种组织的系统组织,这些组件包括Web服务器,应用服务器,数据库,存储,通讯层),它们彼此或和环境存在关系。系统架构的目标是解决利益相关者的关注点。