该文章内容发布已经超过一年,请注意检查文章中内容是否过时。
在上一章中我们详细看了服务配置ServiceConfig类型的初始化,不过我们跳过了AbstractMethodConfig的构造器中创建模块模型对象的过程,那这一章我们就来看下模块模型对象的初始化过程:
那为什么会在Dubbo3的新版本中加入这个域模型呢,主要有如下原因 之前dubbo都是只有一个作用域的,通过静态类 属性共享 增加域模型是为了:
可能比较抽象,可以具体点来看。Dubbo3中在启动时候需要启动配置中心、元数据中心,这个配置中心和元数据中心可以归应用模型来管理。Dubbo作为RPC框架又需要启动服务和引用服务,服务级别的管理就交给了这个模块模型来管理。分层次的管理方便我们理解和处理逻辑,父子级别的模型又方便了数据传递。
了解过JVM类加载机制的同学应该就比较清楚JVM类加载过程中的数据访问模型。子类加载器先交给父类加载器查找,找不到再从子类加载器中查找。Dubbo的分层模型类似这样一种机制,这一章先来简单了解下,后面用到时候具体细说。
为了不增加复杂性,我们这里仅仅列出模型对象类型类型之间的继承关系如下所示:
模型对象一共有4个,公共的属性和操作放在了域模型类型中,下面我们来详细说下这几个模型类型:
ExtensionAccessor 扩展的统一访问器
ScopeModel 模型对象的公共抽象父类型
FrameworkModel dubbo框架模型,可与多个应用程序共享
ApplicationModel 表示正在使用Dubbo的应用程序,并存储基本元数据信息,以便在RPC调用过程中使用。 ApplicationModel包括许多关于发布服务的ProviderModel和许多关于订阅服务的Consumer Model。
ModuleModel 服务模块的模型
了解了这几个模型对象的关系我们可以了解到这几个模型对象的管理层级从框架到应用程序,然后到模块的管理(FrameworkModel->ApplicationModel->ModuleModel),他们主要用来针对框架,应用程序,模块的存储,发布管理,,配置管理
看来Dubbo3 针对应用服务治理与运维这一块也是在努力尝试.
模块模型(ModuleModel)参数对象的创建 这个AbstractMethodConfig构造器在初始化的时候调调用了这么一行代码做为参数向父类型传递对象.
默认情况下使用ApplicationModel的静态方法获取默认的模型对象和默认的模块对象
ApplicationModel(应用程序领域模型)类型中获取默认模型对象的方法:
这里可以看到要想获取应用程序模型必须先通过框架领域模型来获取层级也是框架领域模型到应用程序领域模型
FrameworkModel(框架模型)的默认模型获取工厂方法defaultModel()
FrameworkModel中的重置默认框架模型resetDefaultFrameworkModel
上面单例做了很多的初始化操作,这里开始调用构造器来创建框架模型对象,如下代码:
FrameworkModel()构造器
ExtensionScope.FRAMEWORK
FrameworkModel框架模型的初始化方法initialize()
继续上面代码的调用链路,我们来看 FrameworkModel的super.initialize();方法 调用父类型ScopeModel的initialize()方法
ScopeModel类型的初始化方法initialize():
TypeDefinitionBuilder的初始化类型构造器方法initBuilders
FrameworkServiceRepository对象的初始化
域模型初始化器的获取与初始化(ScopeModelInitializer类型和initializeFrameworkModel方法) 加载到的ScopeModelInitializer类型的SPI扩展实现
通过Debug查到域模型初始化器的SPI扩展类型有如下8个:
这里我随机找两个说一下吧: 容错域模型初始化器:ClusterScopeModelInitializer的initializeFrameworkModel方法:
创建ApplicationConfig对象让后将其添加至应用模型中 内部应用程序模型,这里为应用配置管理器设置一个应用配置对象,将这个应用配置的模块名字配置名字设置为DUBBO_INTERNAL_APPLICATION,应用配置记录着我们常见的应用配置信息,如下面表格所示:
来自官网目前版本的配置解释: 官网当前的配置描述知道到了元数据类型,后面我再补充几个
属性 | 对应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以上版本 |
当前在Dubbo3.0.7中还有一些的配置我下面列举下:
属性 | 对应URL参数 | 类型 | 是否必填 | 缺省值 | 作用 | 描述 | 兼容性 |
---|---|---|---|---|---|---|---|
register-consumer | register-consumer | boolean | 可选 | false | 服务治理 | 是否注册使用者实例,默认为false。 | |
register-mode | register-mode | string | 可选 | all | 服务治理 | 将interface/instance/all 地址注册到注册中心,默认为all。 | |
enable-empty-protection | enable-empty-protection | boolean | 可选 | true | 服务治理 | 在空地址通知上启用空保护,默认为true | |
protocol | protocol | string | 可选 | dubbo | 服务治理 | 此应用程序的首选协议(名称) |
ApplicationModel对象的初始化调用 在前面 3.2.4 FrameworkModel框架模型的初始化方法initialize() 章节中,我们看到了代码ApplicationModel对象的初始化调用如下代码,这里我们来详细说一下:
ApplicationModel(FrameworkModel frameworkModel, boolean isInternal) 刚刚3.2.9那个地方我们看到了使用代码new ApplicationModel(this, true) 来创建对象这里我们详细看下代码细节:
FrameworkModel的添加应用程序方法addApplication:
内部id生成算法buildInternalId方法代码如下: 看代码胜过,文字解释
重置默认的应用模型对象 FrameworkModel 重置默认的应用模型对象 resetDefaultAppModel()方法 与默认框架模型设置方式类似取集合的第一个,这里应用模型需要使用公开的应用模型的第一个做为默认应用模型,代码如下所示:
ApplicationModel的初始化initialize()方法 在前面3.2.10 ApplicationModel的构造器ApplicationModel(FrameworkModel frameworkModel, boolean isInternal) 中的最后一行开始初始化应用模型我们还未详细说明下面可以来看下
先简单说下ConfigManager的作用,无锁配置管理器(通过ConcurrentHashMap),用于快速读取操作。写入操作锁带有配置类型的子配置映射,用于安全检查和添加新配置。 其实ConfigManager实现类中并没有这个初始化方法initialize,不过ConfigManager的父类型AbstractConfigManager中是有initialize方法的,如下所示:
AbstractConfigManager的初始化方法initialize
这是一个与环境配置有关系的类型,我们先来简单了解下它的初始化方法,后期再详细说明:
Environment类型的initialize方法
ConfigUtils中读取迁移规则配置文件loadMigrationRule 这个我们不细说了,贴一下代码感兴趣可以了解下,这个代码主要是读取文件到内存字符串:
前面ApplicationModel对象初始化的时候创建了ModuleModel如下代码:
这里我们来看下这个它所对应的构造器
如上面代码所示调用如下代码将模块模型添加到应用模型中:
这里我们来看下添加过程
前面ModuleModel构造器中通过initialize()方法来进行初始化操作如下代码:
ModuleServiceRepository是模块模型中用来存储服务的通过如下代码调用
这里我们来看下模块服务存储库的构造器代码:
ModuleServiceRepository存储库中使用框架存储库frameworkServiceRepository来间接存储 这里我们看下怎么通过模块模型获取框架服务存储库frameworkServiceRepository:通过代码
ScopeModelUtil工具类获取getFrameworkModel代码如下:
ModuleConfigManager的构造器代码如下:
ModuleConfigManager类型的初始化方法代码如下:
ModuleEnvironment的初始化
OrderedPropertiesConfiguration对象的创建