DubboBootstrap启动类

2021-02-06  本文已影响0人  爱健身的兔子

1 DubboBootstrap的作用

DubboBootstrap类是Dubbo中非常重要的启动类,主要功能包括:

  1. 持有ConfigManagerEnvironment对象并且对其初始化,这两个对象都是与配置相关的;
  2. 更新配置中心配置对象ConfigCenterConfig的属性值;
  3. 加载元数据中心对象;
  4. 检查各个配置对象的属性值是否合法;
  5. 注册java的关闭钩子;
  6. 服务端服务的暴露。

该对象在一个dubbo实例中只能有一个,通过静态方法getInstance获取。getInstance方法调用DubboBootstrap的无参构造方法,在无参构造方法中创建了ConfigManagerEnvironment对象,之后将DubboShutdownHook关闭钩子注册到java中。

1.1 ConfigManager

ConfigManager存储了所有dubbo的配置对象:

类似于一个本地的配置中心,如果要查询配置信息,访问ConfigManager获取对应的配置对象即可,任何配置对象修改了,都要刷新ConfigManager,比如ApplicationConfig修改了属性值,便会调用refreshAll方法修改ConfigManager。 这些配置对象都存储在该对象的属性configsCache中,该属性是一个HashMap对象,因为HashMap不是线程安全的,所以提供了属性lock(ReadWriteLock对象)对访问属性configsCache的操作加锁。 ConfigManager提供了大量的setXXXaddXXX方法,这些方法最终都是调用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获取对象的。 因为AbstractConfigaddIntoConfigManager方法有注解@PostConstruct,因此在AbstractConfig对象创建完毕后,spring会自动调用addIntoConfigManager方法,在该方法中将配置对象添加到ConfigManager中。通过addIntoConfigManager方法保证了所有的配置对象都会存储到ConfigManager中。 DubboBootstrap也提供了大量的方法用于向ConfigManager中添加配置对象以及从ConfigManager中获取配置对象。

1.2 Environment

Environment也是存储配置信息,与ConfigManager不同的是,Environment主要处理的与系统配置相关,比如Java系统配置,以及配置中心的配置。 获取Environment对象,是通过ApplicationModel.getEnvironment()得到。

Environment包含了如下几个配置对象:

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;
}

流程说明

  1. initialize,初始化系统;

  2. exportServices,暴露服务;

  3. isOnlyRegisterProviderhasExportedServices,判断是否需要暴露metadataService

  4. exportMetadataService,暴露MetadataService

  5. registerServiceInstance,将dubbo实例注册到专用于服务发现的注册中心;

  6. referServices,设置ReferenceConfigbootstrap属性;

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实现类,包括:

只有Environmentinitialize方法才有实现,Environment首先从ConfigManager获取默认的配置中心对象ConfigCenterConfig,如果存在ConfigCenterConfig对象,那么将ConfigCenterConfigexternalConfigurationappExternalConfiguration两个属性值设置到Environment的名字一致的两个属性上。

3.2 startConfigCenter

该方法从ConfigManager中获得的所有的ConfigCenterConfig对象。然后访问配置中心的配置,将这些配置保存到Environment对象,最后使用这些配置更新ApplicationConfigMonitorConfigModuleConfig等对象的属性。 配置中心可以有多个,在获取配置的时候,顺次访问每个配置中心,配置保存到本地时后访问的配置中心配置会覆盖之前的配置数据。

3.3 useRegistryAsConfigCenterIfNecessary

如果在方法startConfigCenter中,从ConfigManager里面没有找到ConfigCenterConfig对象,那么在本方法里面,会判断注册中心配置对象RegistryConfiguseAsConfigCenter值:

  1. 如果useAsConfigCenter=null或者true,那么就将注册中心作为配置中心,接下来创建对象ConfigCenterConfig,并将RegistryConfig中的地址、协议、用户名等信息设置到ConfigCenterConfig中,然后将ConfigCenterConfig对象添加到ConfigManager,最后再执行一次startConfigCenter

  2. 对于其他的useAsConfigCenter值,dubbo跳过该注册中心RegistryConfig

useAsConfigCenter默认为null。dubbo可以配置多个注册中心和配置中心。

3.4 startMetadataReport

该方法主要是创建对象MetadataReport,建立与元数据中心的连接。 MetadataReportConfig是元数据中心,用于存储dubbo的元数据配置信息, ApplicationConfigmetadataType字段用于指定元数据中心的类型,有两个值:

该方法首先检查metadataType,如果类型是remote,那么必须配置MetadataReportConfig 。然后该方法使用SPI加载MetadataReportFactory对象,之后通过MetadataReportFactory对象创建MetadataReport对象,MetadataReport对象在构造方法中建立与元数据中心的连接。dubbo使用MetadataReport访问元数据中心。 元数据中心可以配置多个,但是只会使用其中一个。

3.5 loadRemoteConfigs

创建RegistryConfigProtocolConfig对象,并设置其属性。 该方法首先从Environment对象的appExternalConfigurationMapexternalConfigurationMap字段中获取所有的ProtocolConfigRegistryConfigid值,根据id值创建对应的RegistryConfigProtocolConfig对象。之后使用Environment对象设置RegistryConfigProtocolConfig对象的各个属性。以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

检查各个配置对象的各个属性设置的值是否合法,检查内容包括是否有非法字符,长度是否超长。 检查的对象包括:

3.7 initMetadataService

通过SPI加载WritableMetadataService实现类,实现类的名字是由ApplicationConfig类的metadataType字段指定的。

WritableMetadataService包含两个实现类:

3.8 initMetadataServiceExporter

initMetadataServiceExporter创建ConfigurableMetadataServiceExporter对象,将initMetadataService方法加载的WritableMetadataService对象作为其属性。ConfigurableMetadataServiceExporter的作用是将WritableMetadataService对象以dubbo服务的形式对外提供服务,这样客户端便可以使用dubbo协议访问MetadataService接口里面的方法。 initMetadataServiceExporter仅仅是创建ConfigurableMetadataServiceExporter对象,对外发布服务是在DubboBootstrapstart方法里面完成的。

3.9 initEventListener

本方法是将DubboBootstrap对象注册为监听器。 dubbo有自己实现的事件发布机制,其接口是EventDispatcher,默认实现是DirectEventDispatcherDubboBootstrap监听所有dubbo的org.apache.dubbo.event.Event事件。

https://blog.csdn.net/weixin_38308374/article/details/105957522

上一篇下一篇

猜你喜欢

热点阅读