Spring中的EurekaServer啟動(dòng)詳解
EurekaServer啟動(dòng)
看方法上的注釋,初始化eureka,包含eureka集群的同步和發(fā)布注冊(cè),這個(gè)方法時(shí)重寫ServletContextListener#contextInitialized,是eureka啟動(dòng)的入口了。
在 Servlet 容器( 例如 Tomcat、Jetty )啟動(dòng)時(shí),調(diào)用 #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環(huán)境信息 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的環(huán)境
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()中,其實(shí)就是初始化ConfigurationManager的實(shí)例
(1)創(chuàng)建一個(gè)ConcurrentCompositeConfiguration實(shí)例,代表了所謂的配置,包括了eureka需要的所有的配置。在初始化這個(gè)實(shí)例的時(shí)候,調(diào)用了clear()方法,fireEvent()發(fā)布了一個(gè)事件(EVENT_CLEAR),fireEvent()這個(gè)方法其實(shí)是父類的方法,牽扯比較復(fù)雜的另外一個(gè)項(xiàng)目(ConfigurationManager本身不是屬于eureka的源碼,是屬于netflix config項(xiàng)目的源碼)。
/** * 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)就是往上面的那個(gè)ConcurrentCompositeConfiguration實(shí)例加入了一堆別的config,然后搞完了以后,就直接返回了這個(gè)實(shí)例,就是作為所謂的那個(gè)配置的單例
(3)初始化數(shù)據(jù)中心的配置,如果沒(méi)有配置的話,就是DEFAULT data center
(4)初始化eurueka運(yùn)行的環(huán)境,如果你沒(méi)有配置的話,默認(rèn)就給你設(shè)置為test環(huán)境
(5)initEurekaEnvironment的初始化環(huán)境的邏輯
初始化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); //初始化一個(gè)ApplicationInfoManager,對(duì)應(yīng)的其實(shí)是一個(gè)eureka-client。 ApplicationInfoManager applicationInfoManager = null; //初始化eureka-server內(nèi)部的一個(gè)eureka-client,用來(lái)和其他eureka-server節(jié)點(diǎn)用來(lái)注冊(cè)通信的 if (eurekaClient == null) { //CommonConstants. 用來(lái)獲取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(); } //處理注冊(cè)的相關(guān)事情 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節(jié)點(diǎn) PeerEurekaNodes peerEurekaNodes = getPeerEurekaNodes( registry, eurekaServerConfig, eurekaClient.getEurekaClientConfig(), serverCodecs, applicationInfoManager ); //完成eureka-server上下文的構(gòu)建以及初始化過(guò)程 serverContext = new DefaultEurekaServerContext( eurekaServerConfig, serverCodecs, registry, peerEurekaNodes, applicationInfoManager ); EurekaServerContextHolder.initialize(serverContext); serverContext.initialize(); logger.info("Initialized server context"); // 第六步,處理一點(diǎn)善后的事情,從相鄰的eureka節(jié)點(diǎn)拷貝注冊(cè)信息 int registryCount = registry.syncUp(); //這個(gè)方法就是打開(kāi)注冊(cè)表,可以接收請(qǐng)求 registry.openForTraffic(applicationInfoManager, registryCount); // 注冊(cè)所有的監(jiān)控 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的過(guò)程
(1)創(chuàng)建了一個(gè)DefaultEurekaServerConfig對(duì)象
(2)創(chuàng)建DefaultEurekaServerConfig對(duì)象的時(shí)候,在里面會(huì)有一個(gè)init方法
(3)先是將eureka-server.properties中的配置加載到了一個(gè)Properties對(duì)象中,然后將Properties對(duì)象中的配置放到ConfigurationManager中去,此時(shí)ConfigurationManager中去就有了所有的配置了
(4)然后DefaultEurekaServerConfig提供的獲取配置項(xiàng)的各個(gè)方法,都是通過(guò)硬編碼的配置項(xiàng)名稱,從DynamicPropertyFactory中獲取配置項(xiàng)的值,DynamicPropertyFactory是從ConfigurationManager那兒來(lái)的,所以也包含了所有配置項(xiàng)的值
(5)在獲取配置項(xiàng)的時(shí)候,如果沒(méi)有配置,那么就會(huì)有默認(rèn)的值,全部屬性都是有默認(rèn)值的
創(chuàng)建 Eureka-Server 請(qǐng)求和響應(yīng)編解碼器
logger.info("Initializing the eureka client..."); logger.info(eurekaServerConfig.getJsonCodecName()); ServerCodecs serverCodecs = new DefaultServerCodecs(eurekaServerConfig);
創(chuàng)建Eureka-Client
//初始化一個(gè)ApplicationInfoManager,對(duì)應(yīng)的其實(shí)是一個(gè)eureka-client。 ApplicationInfoManager applicationInfoManager = null; //初始化eureka-server內(nèi)部的一個(gè)eureka-client,用來(lái)和其他eureka-server節(jié)點(diǎn)用來(lái)注冊(cè)通信的 if (eurekaClient == null) { //CommonConstants. 用來(lái)獲取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()這個(gè)無(wú)參構(gòu)造中,最終會(huì)去讀取eureka-client.properties的配置,去提供一些默認(rèn)值。
因?yàn)閑ureka-server本身也是一個(gè)eureka-client,因?yàn)楫?dāng)組成集群的時(shí)候,它自己也要向別的服務(wù)端進(jìn)行注冊(cè)
//初始化一個(gè)ApplicationInfoManager,對(duì)應(yīng)的其實(shí)是一個(gè)eureka-client。 ApplicationInfoManager applicationInfoManager = null; //初始化eureka-server內(nèi)部的一個(gè)eureka-client,用來(lái)和其他eureka-server節(jié)點(diǎn)用來(lái)注冊(cè)通信的 if (eurekaClient == null) { //CommonConstants. 用來(lái)獲取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(); }
初始化 EurekaServerContextHolder
EurekaServerContextHolder.initialize(serverContext);
初始化 Eureka-Server 上下文
@PostConstruct @Override public void initialize() { logger.info("Initializing ..."); //啟動(dòng) Eureka-Server 集群節(jié)點(diǎn)集合(復(fù)制) peerEurekaNodes.start(); try { // 初始化 應(yīng)用實(shí)例信息的注冊(cè)表 registry.init(peerEurekaNodes); } catch (Exception e) { throw new RuntimeException(e); } logger.info("Initialized"); }
從其他 Eureka-Server 拉取注冊(cè)信息
// 第六步,處理一點(diǎn)善后的事情,從相鄰的eureka節(jié)點(diǎn)拷貝注冊(cè)信息 int registryCount = registry.syncUp(); //這個(gè)方法就是打開(kāi)注冊(cè)表,可以接收請(qǐng)求 registry.openForTraffic(applicationInfoManager, registryCount);
注冊(cè)監(jiān)控
EurekaMonitors.registerAllStats();
到此這篇關(guān)于Spring中的EurekaServer啟動(dòng)詳解的文章就介紹到這了,更多相關(guān)EurekaServer啟動(dòng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Spring中Eureka的服務(wù)下線詳解
- Spring中Eureka的自我保護(hù)詳解
- Spring的Eureka續(xù)約(心跳檢測(cè))詳解
- Spring中的Eureka服務(wù)過(guò)期詳細(xì)解析
- SpringCloud啟動(dòng)eureka server后,沒(méi)報(bào)錯(cuò)卻不能訪問(wèn)管理頁(yè)面(404問(wèn)題)
- 解決Error:(5,55)java:程序包org.springframework.cloud.netflix.eureka.server不存在問(wèn)題
- SpringCloud集成Eureka并實(shí)現(xiàn)負(fù)載均衡的過(guò)程詳解
- SpringCloud中的Eureka注冊(cè)中心詳細(xì)解讀
相關(guān)文章
解決kafka:org.apache.kafka.common.errors.TimeoutException問(wèn)題
這篇文章主要介紹了解決kafka:org.apache.kafka.common.errors.TimeoutException問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01SpringMVC轉(zhuǎn)發(fā)與重定向參數(shù)傳遞的實(shí)現(xiàn)詳解
這篇文章主要介紹了SpringMVC轉(zhuǎn)發(fā)與重定向參數(shù)傳遞,對(duì)于重定向,可以通過(guò)FlashMap或RedirectAttributes來(lái)在請(qǐng)求間傳遞數(shù)據(jù),因?yàn)橹囟ㄏ蛏婕皟蓚€(gè)獨(dú)立的HTTP請(qǐng)求,而轉(zhuǎn)發(fā)則在同一請(qǐng)求內(nèi)進(jìn)行,數(shù)據(jù)可以直接通過(guò)HttpServletRequest共享,需要的朋友可以參考下2022-07-07史上最佳springboot Locale 國(guó)際化方案
今天給大家分享史上最佳springboot Locale 國(guó)際化方案,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-08-08