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ù)中心的配置,如果沒有配置的話,就是DEFAULT data center
(4)初始化eurueka運(yùn)行的環(huán)境,如果你沒有配置的話,默認(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,用來和其他eureka-server節(jié)點(diǎn)用來注冊(cè)通信的
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();
}
//處理注冊(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)建以及初始化過程
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è)方法就是打開注冊(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的過程
(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è)方法,都是通過硬編碼的配置項(xiàng)名稱,從DynamicPropertyFactory中獲取配置項(xiàng)的值,DynamicPropertyFactory是從ConfigurationManager那兒來的,所以也包含了所有配置項(xiàng)的值
(5)在獲取配置項(xiàng)的時(shí)候,如果沒有配置,那么就會(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,用來和其他eureka-server節(jié)點(diǎn)用來注冊(cè)通信的 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()這個(gè)無參構(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,用來和其他eureka-server節(jié)點(diǎn)用來注冊(cè)通信的
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();
}初始化 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è)方法就是打開注冊(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ù)過期詳細(xì)解析
- SpringCloud啟動(dòng)eureka server后,沒報(bào)錯(cuò)卻不能訪問管理頁面(404問題)
- 解決Error:(5,55)java:程序包org.springframework.cloud.netflix.eureka.server不存在問題
- SpringCloud集成Eureka并實(shí)現(xiàn)負(fù)載均衡的過程詳解
- SpringCloud中的Eureka注冊(cè)中心詳細(xì)解讀
相關(guān)文章
解決kafka:org.apache.kafka.common.errors.TimeoutException問題
這篇文章主要介紹了解決kafka:org.apache.kafka.common.errors.TimeoutException問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
SpringMVC轉(zhuǎn)發(fā)與重定向參數(shù)傳遞的實(shí)現(xiàn)詳解
這篇文章主要介紹了SpringMVC轉(zhuǎn)發(fā)與重定向參數(shù)傳遞,對(duì)于重定向,可以通過FlashMap或RedirectAttributes來在請(qǐng)求間傳遞數(shù)據(jù),因?yàn)橹囟ㄏ蛏婕皟蓚€(gè)獨(dú)立的HTTP請(qǐng)求,而轉(zhuǎn)發(fā)則在同一請(qǐng)求內(nèi)進(jìn)行,數(shù)據(jù)可以直接通過HttpServletRequest共享,需要的朋友可以參考下2022-07-07

