zoukankan      html  css  js  c++  java
  • EurekaServer启动

    EurekaServer启动

    看方法上的注释,初始化eureka,包含eureka集群的同步和发布注册,这个方法时重写ServletContextListener#contextInitialized,是eureka启动的入口了。在 Servlet 容器( 例如 Tomcat、Jetty )启动时,调用 #contextInitialized() 方法。

        /**
         * 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 {
                //初始化eureka环境信息
                initEurekaEnvironment();
                //初始化eureka的上下文
                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);
            }
        }
    

    初始化eureka的环境

       private static final String TEST = "test";
    
        private static final String ARCHAIUS_DEPLOYMENT_ENVIRONMENT = "archaius.deployment.environment";
    
        private static final String EUREKA_ENVIRONMENT = "eureka.environment";
    
        private static final String CLOUD = "cloud";
        private static final String DEFAULT = "default";
    
        private static final String ARCHAIUS_DEPLOYMENT_DATACENTER = "archaius.deployment.datacenter";
    
        private static final String EUREKA_DATACENTER = "eureka.datacenter";  
    
      protected void initEurekaEnvironment() throws Exception {
            logger.info("Setting the eureka configuration..");
    
            String dataCenter = ConfigurationManager.getConfigInstance().getString(EUREKA_DATACENTER);
            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);
            }
            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");
            }
        }
    

    在ConfigurationManager.getConfigInstance()中,其实就是初始化ConfigurationManager的实例

    (1)创建一个ConcurrentCompositeConfiguration实例,代表了所谓的配置,包括了eureka需要的所有的配置。在初始化这个实例的时候,调用了clear()方法,fireEvent()发布了一个事件(EVENT_CLEAR),fireEvent()这个方法其实是父类的方法,牵扯比较复杂的另外一个项目(ConfigurationManager本身不是属于eureka的源码,是属于netflix config项目的源码)。

        /**
         * Creates an empty CompositeConfiguration object which can then
         * be added some other Configuration files
         */
        public ConcurrentCompositeConfiguration()
        {
            clear();
        }
    
        @Override
        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();
        }
    

    (2)就是往上面的那个ConcurrentCompositeConfiguration实例加入了一堆别的config,然后搞完了以后,就直接返回了这个实例,就是作为所谓的那个配置的单例

    (3)初始化数据中心的配置,如果没有配置的话,就是DEFAULT data center

    (4)初始化eurueka运行的环境,如果你没有配置的话,默认就给你设置为test环境

    (5)initEurekaEnvironment的初始化环境的逻辑

    初始化eureka的上下文

        /**
         * init hook for server context. Override for custom logic.
         */
        protected void initEurekaServerContext() throws Exception {
            //加载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);
    
           //初始化一个ApplicationInfoManager,对应的其实是一个eureka-client。
            ApplicationInfoManager applicationInfoManager = null;
    
            //初始化eureka-server内部的一个eureka-client,用来和其他eureka-server节点用来注册通信的
            if (eurekaClient == null) {
                //CommonConstants. 用来获取client信息
                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();
            }
    
            //处理注册的相关事情
            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
                );
            }
    
            //处理peer节点
            PeerEurekaNodes peerEurekaNodes = getPeerEurekaNodes(
                    registry,
                    eurekaServerConfig,
                    eurekaClient.getEurekaClientConfig(),
                    serverCodecs,
                    applicationInfoManager
            );
    
            //完成eureka-server上下文的构建以及初始化过程
            serverContext = new DefaultEurekaServerContext(
                    eurekaServerConfig,
                    serverCodecs,
                    registry,
                    peerEurekaNodes,
                    applicationInfoManager
            );
    
            EurekaServerContextHolder.initialize(serverContext);
    
            serverContext.initialize();
            logger.info("Initialized server context");
    
            // 第六步,处理一点善后的事情,从相邻的eureka节点拷贝注册信息
            int registryCount = registry.syncUp();
            //这个方法就是打开注册表,可以接收请求
            registry.openForTraffic(applicationInfoManager, registryCount);
    
            // 注册所有的监控
            EurekaMonitors.registerAllStats();
        }
    

    配置文件读取

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

    加载eureka-server.properties的过程:

    (1)创建了一个DefaultEurekaServerConfig对象

    (2)创建DefaultEurekaServerConfig对象的时候,在里面会有一个init方法

    (3)先是将eureka-server.properties中的配置加载到了一个Properties对象中,然后将Properties对象中的配置放到ConfigurationManager中去,此时ConfigurationManager中去就有了所有的配置了

    (4)然后DefaultEurekaServerConfig提供的获取配置项的各个方法,都是通过硬编码的配置项名称,从DynamicPropertyFactory中获取配置项的值,DynamicPropertyFactory是从ConfigurationManager那儿来的,所以也包含了所有配置项的值

    (5)在获取配置项的时候,如果没有配置,那么就会有默认的值,全部属性都是有默认值的

    创建 Eureka-Server 请求和响应编解码器

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

    创建Eureka-Client

           //初始化一个ApplicationInfoManager,对应的其实是一个eureka-client。
            ApplicationInfoManager applicationInfoManager = null;
    
            //初始化eureka-server内部的一个eureka-client,用来和其他eureka-server节点用来注册通信的
            if (eurekaClient == null) {
                //CommonConstants. 用来获取client信息
                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();
            }
    

    在new MyDataCenterInstanceConfig()这个无参构造中,最终会去读取eureka-client.properties的配置,去提供一些默认值。

    image-20211008155824162

    因为eureka-server本身也是一个eureka-client,因为当组成集群的时候,它自己也要向别的服务端进行注册

     //处理注册的相关事情
            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
                );
            }
    
            //处理peer节点
            PeerEurekaNodes peerEurekaNodes = getPeerEurekaNodes(
                    registry,
                    eurekaServerConfig,
                    eurekaClient.getEurekaClientConfig(),
                    serverCodecs,
                    applicationInfoManager
            );
    
            //完成eureka-server上下文的构建以及初始化过程
            serverContext = new DefaultEurekaServerContext(
                    eurekaServerConfig,
                    serverCodecs,
                    registry,
                    peerEurekaNodes,
                    applicationInfoManager
            );
    

    初始化 EurekaServerContextHolder

    EurekaServerContextHolder.initialize(serverContext);
    

    初始化 Eureka-Server 上下文

        @PostConstruct
        @Override
        public void initialize() {
            logger.info("Initializing ...");
            //启动 Eureka-Server 集群节点集合(复制)
            peerEurekaNodes.start();
            try {
                // 初始化 应用实例信息的注册表
                registry.init(peerEurekaNodes);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            logger.info("Initialized");
        }
    

    从其他 Eureka-Server 拉取注册信息

    // 第六步,处理一点善后的事情,从相邻的eureka节点拷贝注册信息
            int registryCount = registry.syncUp();
            //这个方法就是打开注册表,可以接收请求
            registry.openForTraffic(applicationInfoManager, registryCount);
    

    注册监控

    EurekaMonitors.registerAllStats();
    
  • 相关阅读:
    os.environ的详解
    request.headers.get头部获取内容的缺失
    mysql根据逗号分割的字符串去关联查询另外一个表的数据
    Flask路由中使用正则表达式匹配
    Mac OS下安装mysqlclient遇到的一些坑
    【uWSGI】 listen queue of socket (fd: 3) 错误分析
    redis zset底层实现原理
    计算机网络05 传输层
    计算机网络04 网络层
    计算机网络03 数据链路层
  • 原文地址:https://www.cnblogs.com/dalianpai/p/15380755.html
Copyright © 2011-2022 走看看