[Source learn together - Micro Services] Nexflix Eureka source two: EurekaServer start of the configuration file to load and interfaces for configuration items read

Foreword

The article describes why have read netflix eureka source, and there is no longer an overview, let's start official source content interpretation.

Should the reprint please indicate the source: a flower count romantic

Code Overview

Remember the above, we find a eureka server through web.xml entry class EurekaBootStrap, where we will first take a brief look:

/**
 * The class that kick starts the eureka server. 负责启动Eureka server的类
 *
 * <p>
 * 这里要注意两个关键点:
 * eureka server对应的配置类为:EurekaServerConfig
 * eureka client对应的配置类为:EurekaInstanceConfig
 *
 * The eureka server is configured by using the configuration
 * {@link EurekaServerConfig} specified by <em>eureka.server.props</em> in the
 * classpath.  The eureka client component is also initialized by using the
 * configuration {@link EurekaInstanceConfig} specified by
 * <em>eureka.client.props</em>. If the server runs in the AWS cloud, the eureka
 * server binds it to the elastic ip as specified.
 * </p>
 *
 * @author Karthik Ranganathan, Greg Kim, David Liu
 *
 * 负责EurekaServer初始化的类
 */
public class EurekaBootStrap implements ServletContextListener {
    /**
     * Initializes Eureka, including syncing up with other Eureka peers and publishing the registry.
     *
     * @see
     * javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
     */
    @Override
    public void contextInitialized(ServletContextEvent event) {
        try {
            initEurekaEnvironment();
            initEurekaServerContext();

            ServletContext sc = event.getServletContext();
            sc.setAttribute(EurekaServerContext.class.getName(), serverContext);
        } catch (Throwable e) {
            logger.error("Cannot bootstrap eureka server :", e);
            throw new RuntimeException("Cannot bootstrap eureka server :", e);
        }
    }
}

Notes look we can understand a few key points:

  1. eureka server configuration corresponding class: EurekaServerConfig
  2. eureka client configuration corresponding class: EurekaInstanceConfig
  3. EurekaBootStrap implements ServletContextListener, so here performs contextInitialized methods directly.

Eureka-Server environment configuration

Initialization enviroment

Then down to taking a step forward with, where you can look at initEurekaEnvironment()

code show as below:

protected void initEurekaEnvironment() throws Exception {
        logger.info("Setting the eureka configuration..");

        // 获取dataCenter数据中心 这里重点看ConfigurationManager
        // ConfigurationManager:配置管理器,管理eureka自己所有的配置,
        // 重点:getConfigInstance里面使用的是volatile+synchronized+double check模式的单例模式
        /**
         * ConfigurationManager 创建过程:(继续往后跟读代码)
         * 1、创建一个ConcurrentCompositeConfiguration实例,这个类代表了所谓的配置,包括eureka需要的所有配置。
         * 2、往ConcurrentCompositeConfiguration加入一堆config,然后返回ConfigurationManager实例
         * 3、初始化数据中心的配置,如果没有配置的话就是default data center
         * 4、初始化eureka 运行的环境,如果没有配置的话,默认就是test环境
         */
        String dataCenter = ConfigurationManager.getConfigInstance().getString(EUREKA_DATACENTER);
        // 初始化数据中心,没有配置的话 使用DEFAULT data center
        if (dataCenter == null) {
            logger.info("Eureka data center value eureka.datacenter is not set, defaulting to default");
            ConfigurationManager.getConfigInstance().setProperty(ARCHAIUS_DEPLOYMENT_DATACENTER, DEFAULT);
        } else {
            ConfigurationManager.getConfigInstance().setProperty(ARCHAIUS_DEPLOYMENT_DATACENTER, dataCenter);
        }
        // 获取eureka server运行环境,没有配置的话默认使用test环境
        // 后面读取配置文件会根据运行环境读取,比如eureka-server-test.properties
        String environment = ConfigurationManager.getConfigInstance().getString(EUREKA_ENVIRONMENT);
        if (environment == null) {
            ConfigurationManager.getConfigInstance().setProperty(ARCHAIUS_DEPLOYMENT_ENVIRONMENT, TEST);
            logger.info("Eureka environment value eureka.environment is not set, defaulting to test");
        }
    }

Here's a more detailed written comments, and there are two main points:

  1. getConfigInstance used inside the singleton volatile + synchronized + double check mode
  2. ConfigurationManager creation process

getConfigInstance

A key point here is to use the classic double check singleton.

This single example is a thread-safe manner, which uses a volatile + synchronized + double check, specific seconds will not start where I explain here, search double check Singleton will be a lot analytical articles directly here look at the code.

static volatile AbstractConfiguration instance = null;

/**
 * Get the current system wide configuration. If there has not been set, it will return a default
 * {@link ConcurrentCompositeConfiguration} which contains a SystemConfiguration from Apache Commons
 * Configuration and a {@link DynamicURLConfiguration}.
 */
public static AbstractConfiguration getConfigInstance() {
    if (instance == null) {
        synchronized (ConfigurationManager.class) {
            if (instance == null) {
                instance = getConfigInstance(Boolean.getBoolean(DynamicPropertyFactory.DISABLE_DEFAULT_CONFIG));
            }
        }
    }
    return instance;
}

Here instance with volatile modified to ensure visibility between threads, with the thread to ensure serialization synchronized, double check to ensure that no cases of sheets.

Then we continue with down, take a look at the process of creating the ConfigurationManager.

Creating ConfigurationManager

private static AbstractConfiguration getConfigInstance(boolean defaultConfigDisabled) {
    if (instance == null && !defaultConfigDisabled) {
        instance = createDefaultConfigInstance();
        registerConfigBean();
    }
    return instance;        
}

private static AbstractConfiguration createDefaultConfigInstance() {
    ConcurrentCompositeConfiguration config = new ConcurrentCompositeConfiguration();  
    try {
        DynamicURLConfiguration defaultURLConfig = new DynamicURLConfiguration();
        config.addConfiguration(defaultURLConfig, URL_CONFIG_NAME);
    } catch (Throwable e) {
        logger.warn("Failed to create default dynamic configuration", e);
    }
    if (!Boolean.getBoolean(DISABLE_DEFAULT_SYS_CONFIG)) {
        SystemConfiguration sysConfig = new SystemConfiguration();
        config.addConfiguration(sysConfig, SYS_CONFIG_NAME);
    }
    if (!Boolean.getBoolean(DISABLE_DEFAULT_ENV_CONFIG)) {
        EnvironmentConfiguration envConfig = new EnvironmentConfiguration();
        config.addConfiguration(envConfig, ENV_CONFIG_NAME);
    }
    ConcurrentCompositeConfiguration appOverrideConfig = new ConcurrentCompositeConfiguration();
    config.addConfiguration(appOverrideConfig, APPLICATION_PROPERTIES);
    config.setContainerConfigurationIndex(config.getIndexOfConfiguration(appOverrideConfig));
    return config;
}

public ConcurrentCompositeConfiguration()
{
    clear();
}

public final void clear()
{
    fireEvent(EVENT_CLEAR, null, null, true);
    configList.clear();
    namedConfigurations.clear();
    // recreate the in memory configuration
    containerConfiguration = new ConcurrentMapConfiguration();
    containerConfiguration.setThrowExceptionOnMissing(isThrowExceptionOnMissing());
    containerConfiguration.setListDelimiter(getListDelimiter());
    containerConfiguration.setDelimiterParsingDisabled(isDelimiterParsingDisabled());
    containerConfiguration.addConfigurationListener(eventPropagater);
    configList.add(containerConfiguration);
    
    overrideProperties = new ConcurrentMapConfiguration();
    overrideProperties.setThrowExceptionOnMissing(isThrowExceptionOnMissing());
    overrideProperties.setListDelimiter(getListDelimiter());
    overrideProperties.setDelimiterParsingDisabled(isDelimiterParsingDisabled());
    overrideProperties.addConfigurationListener(eventPropagater);
    
    fireEvent(EVENT_CLEAR, null, null, false);
    containerConfigurationChanged = false;
    invalidate();
}

The code above is more, if the line by line to pull the details really is not necessary, here we just look at some key processes, we note above also written about the process of creating the ConfigurationManager:
1, create a ConcurrentCompositeConfiguration instance, this class represents the so-called configuration, including all configurations eureka need.
2, was added to the pile ConcurrentCompositeConfiguration config, and then returns instance ConfigurationManager

Here I do not recommend too buckle detail, since it is often the minutiae of these things will go around us.

Specific details about the ConfigurationManager There are also two good articles recommended:

  1. Notes Eureka start
  2. Micro dynamic service configuration component netflix archaius

Eureka-Server context load

Look at the code:

protected void initEurekaServerContext() throws Exception {
    // 1、加载eureka-server properties文件中和配置
    EurekaServerConfig eurekaServerConfig = new DefaultEurekaServerConfig();

    // For backward compatibility
    JsonXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), XStream.PRIORITY_VERY_HIGH);
    XmlXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), XStream.PRIORITY_VERY_HIGH);

    logger.info("Initializing the eureka client...");
    logger.info(eurekaServerConfig.getJsonCodecName());
    ServerCodecs serverCodecs = new DefaultServerCodecs(eurekaServerConfig);

    // 2、初始化一个ApplicationInfoManager,和第3步创建eureka client相关,后续会讲解
    ApplicationInfoManager applicationInfoManager = null;

    // 3、初始化eureka-server内部的一个eureka-client(用来跟其他的eureka-server节点做注册和通信)
    // 类的开头已经说明了:EurekaInstanceConfig其实就是eureka client相关的配置类
    if (eurekaClient == null) {
        EurekaInstanceConfig instanceConfig = isCloud(ConfigurationManager.getDeploymentContext())
                ? new CloudInstanceConfig()
                : new MyDataCenterInstanceConfig();
        
        applicationInfoManager = new ApplicationInfoManager(
                instanceConfig, new EurekaConfigBasedInstanceInfoProvider(instanceConfig).get());
        
        EurekaClientConfig eurekaClientConfig = new DefaultEurekaClientConfig();
        eurekaClient = new DiscoveryClient(applicationInfoManager, eurekaClientConfig);
    } else {
        applicationInfoManager = eurekaClient.getApplicationInfoManager();
    }

    // 3、处理注册相关的事情
    PeerAwareInstanceRegistry registry;
    if (isAws(applicationInfoManager.getInfo())) {
        registry = new AwsInstanceRegistry(
                eurekaServerConfig,
                eurekaClient.getEurekaClientConfig(),
                serverCodecs,
                eurekaClient
        );
        awsBinder = new AwsBinderDelegate(eurekaServerConfig, eurekaClient.getEurekaClientConfig(), registry, applicationInfoManager);
        awsBinder.start();
    } else {
        registry = new PeerAwareInstanceRegistryImpl(
                eurekaServerConfig,
                eurekaClient.getEurekaClientConfig(),
                serverCodecs,
                eurekaClient
        );
    }

    // 4、处理peer节点相关的事情
    PeerEurekaNodes peerEurekaNodes = getPeerEurekaNodes(
            registry,
            eurekaServerConfig,
            eurekaClient.getEurekaClientConfig(),
            serverCodecs,
            applicationInfoManager
    );

    // 5、完成eureka-server上下文(context)的构建及初始化
    serverContext = new DefaultEurekaServerContext(
            eurekaServerConfig,
            serverCodecs,
            registry,
            peerEurekaNodes,
            applicationInfoManager
    );

    EurekaServerContextHolder.initialize(serverContext);

    serverContext.initialize();
    logger.info("Initialized server context");

    // Copy registry from neighboring eureka node
    // 6、处理一些善后的事情,从相邻的eureka节点拷贝注册信息
    int registryCount = registry.syncUp();
    registry.openForTraffic(applicationInfoManager, registryCount);

    // Register all monitoring statistics.
    // 7、注册所有的监控统计项
    EurekaMonitors.registerAllStats();
}

Code is a little long, loaded context information is divided into several steps above comments, write code comments have

Loading eureka-server properties and configuration file
EurekaServerConfig eurekaServerConfig = new DefaultEurekaServerConfig ();

private static final DynamicStringProperty EUREKA_PROPS_FILE = DynamicPropertyFactory.getInstance().getStringProperty("eureka.server.props","eureka-server");

public DefaultEurekaServerConfig() {
    init();
}

private void init() {
    String env = ConfigurationManager.getConfigInstance().getString(
            EUREKA_ENVIRONMENT, TEST);
    ConfigurationManager.getConfigInstance().setProperty(
            ARCHAIUS_DEPLOYMENT_ENVIRONMENT, env);

    String eurekaPropsFile = EUREKA_PROPS_FILE.get();
    try {
        // ConfigurationManager
        // .loadPropertiesFromResources(eurekaPropsFile);
        ConfigurationManager
                .loadCascadedPropertiesFromResources(eurekaPropsFile);
    } catch (IOException e) {
        logger.warn(
                "Cannot find the properties specified : {}. This may be okay if there are other environment "
                        + "specific properties or the configuration is installed with a different mechanism.",
                eurekaPropsFile);
    }
}

public static void loadCascadedPropertiesFromResources(String configName) throws IOException {
    Properties props = loadCascadedProperties(configName);
    if (instance instanceof AggregatedConfiguration) {
        ConcurrentMapConfiguration config = new ConcurrentMapConfiguration();
        config.loadProperties(props);
        ((AggregatedConfiguration) instance).addConfiguration(config, configName);
    } else {
        ConfigurationUtils.loadProperties(props, instance);
    }
}

First, we look at EurekaServerConfig:
image.png

Which contains a lot of getxxx method, look at the concrete realization:
image.png

ConfigInstance which is DynamicPropertyFactorythe object. EurekaServerConfig, this is the interface, and there are a bunch of methods getXXX (), including all configuration eureka server need to use, can be obtained through this interface.

想象一下,eureka-sever.properties文件里,都是一个一个的key=value的很多的配置项,肯定是将这些key-value格式的配置项加载到内存的Properties对象去存放,Map。一般来说,如果让我们自己来设计这个读取properties文件的配置的代码,也许我们就是做到将配置加载到Properties对象中就结束了。

EurekaServerConfig,代表了eureka-server需要的所有的配置项,通过接口定义了大量的方法,让你可以从这里获取所有你需要的配置

DefaultEurekaServerConfig就是上面EurekaServerConfig的实现类,创建实例的时候,会执行一个init()方法,在这个方法中,就会完成eureka-server.properties文件中的配置项的加载。EUREKA_PROPS_FILE,对应着要加载的eureka的配置文件的名字。

将加载出来的Properties中的配置项都放到ConfigurationManager中去,由这个ConfigurationManager来管理

比如说eureka-server那个工程里,就有一个src/main/resources/eureka-server.properties文件,只不过里面是空的,全部都用了默认的配置

DefaultEurekaServerConfig.init()方法中,会将eureka-server.properties文件中的配置加载出来,都放到ConfdigurationManager中去,然后在DefaultEurekaServerConfig的各种获取配置项的方法中,配置项的名字是在各个方硬编码的,是从一个DynamicPropertyFactory里面去获取的,你可以认为DynamicPropertyFactory是从ConfigurationManager那儿来的,因为ConfigurationManager中都包含了加载出来的配置了,所以DynamicPropertyFactory里,也可以获取到所有的配置项

在从DynamicPropertyFactory中获取配置项的时候,如果你没配置,那么就用默认值,全部都给你弄好了各个配置项的默认值,相当于所有的配置项的默认值,在DefaultEurekaServerConfig的各个方法中,都可以看到,如果你没配置,那么就用这里的默认值就可以了

加载eureka-server.properties的过程:

(1) Create a DefaultEurekaServerConfig objects
(2) when the object DefaultEurekaServerConfig created, in which there is an init method
(3) The first configuration eureka-server.properties loaded into a Properties object, then the object Properties ConfigurationManager go into the configuration, when the ConfigurationManager opinions have all the configurations
of each method for obtaining configuration items (4) and provided DefaultEurekaServerConfig, are acquired from the values of configuration items by the configuration item name DynamicPropertyFactory hardcoded , DynamicPropertyFactory from there to the ConfigurationManager, so it contains the values of all configuration items
(5) to obtain configuration item in time, if not configured, it will have a default value, all attributes are all default values

Declare

This article starting from my blog: https://www.cnblogs.com/wang-meng and public numbers: One ramiflorous be considered romantic , should reprint please indicate the source!

Interested partner may be concerned about the small number of individual public: One branch count romantic flowers

22.jpg

Guess you like

Origin www.cnblogs.com/wang-meng/p/12089911.html