DubboBootstrap启动类
1 DubboBootstrap的作用
DubboBootstrap类是Dubbo中非常重要的启动类,主要功能包括:
- 持有ConfigManager、Environment对象并且对其初始化,这两个对象都是与配置相关的;
- 更新配置中心配置对象ConfigCenterConfig的属性值;
- 加载元数据中心对象;
- 检查各个配置对象的属性值是否合法;
- 注册java的关闭钩子;
- 服务端服务的暴露。
该对象在一个dubbo实例中只能有一个,通过静态方法getInstance
获取。getInstance
方法调用DubboBootstrap
的无参构造方法,在无参构造方法中创建了ConfigManager
、Environment
对象,之后将DubboShutdownHook
关闭钩子注册到java中。
1.1 ConfigManager
ConfigManager
存储了所有dubbo的配置对象:
-
RegistryConfig
-
ConsumerConfig
-
ModuleConfig
-
ProtocolConfig
-
ProviderConfig
-
ApplicationConfig
-
MonitorConfig
类似于一个本地的配置中心,如果要查询配置信息,访问ConfigManager
获取对应的配置对象即可,任何配置对象修改了,都要刷新ConfigManager
,比如ApplicationConfig
修改了属性值,便会调用refreshAll
方法修改ConfigManager
。 这些配置对象都存储在该对象的属性configsCache
中,该属性是一个HashMap
对象,因为HashMap
不是线程安全的,所以提供了属性lock
(ReadWriteLock对象)对访问属性configsCache
的操作加锁。 ConfigManager
提供了大量的setXXX
和addXXX
方法,这些方法最终都是调用addConfig
方法,addConfig
方法将配置对象添加到属性configsCache
中。 属性configsCache
的类型是Map<String, Map<String, AbstractConfig>>
,是一个两层Map结构,第一层的key是配置类名字的变体,比如调用addMetadataReports
增加MetadataReportConfig
对象,那么第一层的key是metadata-report,也就是将类名字的Config去掉,然后在类名字中大写字母前加“-”,最后将所有的大写字母变为小写字母。第二层的key是配置对象中的id
属性的值,如果没有设置id
值,默认使用类名字+“#default”作为key。 在dubbo中,一般访问ConfigManager
,是使用ApplicationModel.getConfigManager()
通过SPI获取对象的。 因为AbstractConfig
的addIntoConfigManager
方法有注解@PostConstruct
,因此在AbstractConfig
对象创建完毕后,spring会自动调用addIntoConfigManager
方法,在该方法中将配置对象添加到ConfigManager
中。通过addIntoConfigManager
方法保证了所有的配置对象都会存储到ConfigManager
中。 DubboBootstrap
也提供了大量的方法用于向ConfigManager
中添加配置对象以及从ConfigManager
中获取配置对象。
1.2 Environment
Environment
也是存储配置信息,与ConfigManager
不同的是,Environment
主要处理的与系统配置相关,比如Java系统配置,以及配置中心的配置。 获取Environment
对象,是通过ApplicationModel.getEnvironment()
得到。
Environment
包含了如下几个配置对象:
-
PropertiesConfiguration
装载"dubbo.properties"文件的配置信息; -
SystemConfiguration
装载System的properties配置系信息; -
EnvironmentConfiguration
装载JVM环境变量的配置信息; -
InmemoryConfiguration
装载内部的配置信息,分为全局配置和应用级配置; -
DynamicConfiguration
装载配置中心的配置信息;
2 DubboBootstrap的启动
DubboBootstrap
的启动流程如下:
public DubboBootstrap start() {
//只能初始化一次
if (started.compareAndSet(false, true)) {
initialize();//调用初始化方法
// 暴露服务
exportServices();
// Not only provider register
if (!isOnlyRegisterProvider() || hasExportedServices()) {
// 暴露MetadataService
exportMetadataService();
// 注册服务实例
registerServiceInstance();
}
//引用
referServices();
}
return this;
}
流程说明
-
initialize
,初始化系统; -
exportServices
,暴露服务; -
isOnlyRegisterProvider
和hasExportedServices
,判断是否需要暴露metadataService
; -
exportMetadataService
,暴露MetadataService
; -
registerServiceInstance
,将dubbo实例注册到专用于服务发现的注册中心; -
referServices
,设置ReferenceConfig
的bootstrap
属性;
3 DubboBootstrap的初始化
DubboBoostrap通过initialize
方法实现初始化,主要包括初始化配置和环境,初始化元数据服务和监听器。
private void initialize() {
if (!initialized.compareAndSet(false, true)) {
return;//initialize方法只能初始化一次
}
ApplicationModel.iniFrameworkExts();//初始化FrameworkExt实现类,这里会调用Environment的initialize方法
startConfigCenter();//启动配置中心
useRegistryAsConfigCenterIfNecessary();//用注册中心作为配置中心
startMetadataReport();//启动MetadataReport
loadRemoteConfigs();//加载远程配置
checkGlobalConfigs();//检查全局配置
initMetadataService();//初始化MetadataService
initMetadataServiceExporter();//初始化MetadataServiceExporter
initEventListener();//初始化事件监听器
}
3.1 ApplicationModel.iniFrameworkExts
初始化FrameworkExt
实现类,包括:
-
ConfigManager
-
Environment
-
ServiceRepository
只有Environment
的initialize
方法才有实现,Environment
首先从ConfigManager
获取默认的配置中心对象ConfigCenterConfig
,如果存在ConfigCenterConfig
对象,那么将ConfigCenterConfig
的externalConfiguration
和appExternalConfiguration
两个属性值设置到Environment
的名字一致的两个属性上。
3.2 startConfigCenter
该方法从ConfigManager
中获得的所有的ConfigCenterConfig
对象。然后访问配置中心的配置,将这些配置保存到Environment对象,最后使用这些配置更新ApplicationConfig
,MonitorConfig
,ModuleConfig
等对象的属性。 配置中心可以有多个,在获取配置的时候,顺次访问每个配置中心,配置保存到本地时后访问的配置中心配置会覆盖之前的配置数据。
3.3 useRegistryAsConfigCenterIfNecessary
如果在方法startConfigCenter
中,从ConfigManager
里面没有找到ConfigCenterConfig
对象,那么在本方法里面,会判断注册中心配置对象RegistryConfig
的useAsConfigCenter
值:
-
如果
useAsConfigCenter=null
或者true
,那么就将注册中心作为配置中心,接下来创建对象ConfigCenterConfig
,并将RegistryConfig
中的地址、协议、用户名等信息设置到ConfigCenterConfig
中,然后将ConfigCenterConfig
对象添加到ConfigManager
,最后再执行一次startConfigCenter
。 -
对于其他的
useAsConfigCenter
值,dubbo跳过该注册中心RegistryConfig
。
useAsConfigCenter
默认为null
。dubbo可以配置多个注册中心和配置中心。
3.4 startMetadataReport
该方法主要是创建对象MetadataReport
,建立与元数据中心的连接。 MetadataReportConfig
是元数据中心,用于存储dubbo的元数据配置信息, ApplicationConfig
的metadataType
字段用于指定元数据中心的类型,有两个值:
-
remote
-
local
该方法首先检查metadataType
,如果类型是remote
,那么必须配置MetadataReportConfig
。然后该方法使用SPI加载MetadataReportFactory
对象,之后通过MetadataReportFactory
对象创建MetadataReport
对象,MetadataReport
对象在构造方法中建立与元数据中心的连接。dubbo使用MetadataReport
访问元数据中心。 元数据中心可以配置多个,但是只会使用其中一个。
3.5 loadRemoteConfigs
创建RegistryConfig
和ProtocolConfig
对象,并设置其属性。 该方法首先从Environment
对象的appExternalConfigurationMap
和externalConfigurationMap
字段中获取所有的ProtocolConfig
和RegistryConfig
的id
值,根据id
值创建对应的RegistryConfig
和ProtocolConfig
对象。之后使用Environment
对象设置RegistryConfig
和ProtocolConfig
对象的各个属性。以RegistryConfig的创建为例,代码如下:
private void loadRemoteConfigs() {
// registry ids to registry configs
List<RegistryConfig> tmpRegistries = new ArrayList<>();
Set<String> registryIds = configManager.getRegistryIds();
registryIds.forEach(id -> {
if (tmpRegistries.stream().noneMatch(reg -> reg.getId().equals(id))) {
tmpRegistries.add(configManager.getRegistry(id).orElseGet(() -> {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setId(id);
registryConfig.refresh();
return registryConfig;
}));
}
});
configManager.addRegistries(tmpRegistries);
// protocol ids to protocol configs
List<ProtocolConfig> tmpProtocols = new ArrayList<>();
Set<String> protocolIds = configManager.getProtocolIds();
protocolIds.forEach(id -> {
if (tmpProtocols.stream().noneMatch(prot -> prot.getId().equals(id))) {
tmpProtocols.add(configManager.getProtocol(id).orElseGet(() -> {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setId(id);
protocolConfig.refresh();
return protocolConfig;
}));
}
});
configManager.addProtocols(tmpProtocols);
}
3.6 checkGlobalConfigs
检查各个配置对象的各个属性设置的值是否合法,检查内容包括是否有非法字符,长度是否超长。 检查的对象包括:
-
ApplicationConfig
-
ConfigCenterConfig
-
MetadataReportConfig
-
MonitorConfig
-
MetricsConfig
-
ModuleConfig
-
SslConfig
3.7 initMetadataService
通过SPI加载WritableMetadataService
实现类,实现类的名字是由ApplicationConfig
类的metadataType
字段指定的。
WritableMetadataService
包含两个实现类:
-
InMemoryWritableMetadataService
-
RemoteWritableMetadataService
3.8 initMetadataServiceExporter
initMetadataServiceExporter
创建ConfigurableMetadataServiceExporter
对象,将initMetadataService
方法加载的WritableMetadataService
对象作为其属性。ConfigurableMetadataServiceExporter
的作用是将WritableMetadataService
对象以dubbo服务的形式对外提供服务,这样客户端便可以使用dubbo协议访问MetadataService
接口里面的方法。 initMetadataServiceExporter
仅仅是创建ConfigurableMetadataServiceExporter
对象,对外发布服务是在DubboBootstrap
的start
方法里面完成的。
3.9 initEventListener
本方法是将DubboBootstrap
对象注册为监听器。 dubbo有自己实现的事件发布机制,其接口是EventDispatcher
,默认实现是DirectEventDispatcher
。 DubboBootstrap
监听所有dubbo的org.apache.dubbo.event.Event
事件。
https://blog.csdn.net/weixin_38308374/article/details/105957522