序
本文主要研究一下spring cloud的EurekaServerInitializerConfiguration
EurekaServerInitializerConfiguration
spring-cloud-netflix-eureka-server-2.0.0.RC1-sources.jar!/org/springframework/cloud/netflix/eureka/server/EurekaServerInitializerConfiguration.java
@Configuration
public class EurekaServerInitializerConfiguration
implements ServletContextAware, SmartLifecycle, Ordered {
//......
@Override
public void start() {
new Thread(new Runnable() {
@Override
public void run() {
try {
//TODO: is this class even needed now?
eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
log.info("Started Eureka Server");
publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
EurekaServerInitializerConfiguration.this.running = true;
publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
}
catch (Exception ex) {
// Help!
log.error("Could not initialize Eureka servlet context", ex);
}
}
}).start();
}
@Override
public void stop() {
this.running = false;
eurekaServerBootstrap.contextDestroyed(this.servletContext);
}
}
这里start的时候调用了contextInitialized方法,然后stop的时候,调用contextDestroyed
EurekaServerBootstrap.contextInitialized
spring-cloud-netflix-eureka-server-2.0.0.RC1-sources.jar!/org/springframework/cloud/netflix/eureka/server/EurekaServerBootstrap.java
public void contextInitialized(ServletContext context) {
try {
initEurekaEnvironment();
initEurekaServerContext();
context.setAttribute(EurekaServerContext.class.getName(), this.serverContext);
}
catch (Throwable e) {
log.error("Cannot bootstrap eureka server :", e);
throw new RuntimeException("Cannot bootstrap eureka server :", e);
}
}
这里initEurekaEnvironment初始化环境配置,重点是initEurekaServerContext
EurekaServerBootstrap.initEurekaServerContext
protected void initEurekaServerContext() throws Exception {
// For backward compatibility
JsonXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(),
XStream.PRIORITY_VERY_HIGH);
XmlXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(),
XStream.PRIORITY_VERY_HIGH);
if (isAws(this.applicationInfoManager.getInfo())) {
this.awsBinder = new AwsBinderDelegate(this.eurekaServerConfig,
this.eurekaClientConfig, this.registry, this.applicationInfoManager);
this.awsBinder.start();
}
EurekaServerContextHolder.initialize(this.serverContext);
log.info("Initialized server context");
// Copy registry from neighboring eureka node
int registryCount = this.registry.syncUp();
this.registry.openForTraffic(this.applicationInfoManager, registryCount);
// Register all monitoring statistics.
EurekaMonitors.registerAllStats();
}
这里调用了EurekaServerContextHolder.initialize(this.serverContext),registry.syncUp(),然后registry.openForTraffic
EurekaServerContextHolder.initialize(this.serverContext)
eureka-core-1.8.8-sources.jar!/com/netflix/eureka/EurekaServerContextHolder.java
/**
* A static holder for the server context for use in non-DI cases.
*
* @author David Liu
*/
public class EurekaServerContextHolder {
private final EurekaServerContext serverContext;
private EurekaServerContextHolder(EurekaServerContext serverContext) {
this.serverContext = serverContext;
}
public EurekaServerContext getServerContext() {
return this.serverContext;
}
private static EurekaServerContextHolder holder;
public static synchronized void initialize(EurekaServerContext serverContext) {
holder = new EurekaServerContextHolder(serverContext);
}
public static EurekaServerContextHolder getInstance() {
return holder;
}
}
主要是给非IOC容器引用EurekaServerContext
syncUp
eureka-core-1.8.8-sources.jar!/com/netflix/eureka/registry/PeerAwareInstanceRegistryImpl.java
/**
* Populates the registry information from a peer eureka node. This
* operation fails over to other nodes until the list is exhausted if the
* communication fails.
*/
@Override
public int syncUp() {
// Copy entire entry from neighboring DS node
int count = 0;
for (int i = 0; ((i < serverConfig.getRegistrySyncRetries()) && (count == 0)); i++) {
if (i > 0) {
try {
Thread.sleep(serverConfig.getRegistrySyncRetryWaitMs());
} catch (InterruptedException e) {
logger.warn("Interrupted during registry transfer..");
break;
}
}
Applications apps = eurekaClient.getApplications();
for (Application app : apps.getRegisteredApplications()) {
for (InstanceInfo instance : app.getInstances()) {
try {
if (isRegisterable(instance)) {
register(instance, instance.getLeaseInfo().getDurationInSecs(), true);
count++;
}
} catch (Throwable t) {
logger.error("During DS init copy", t);
}
}
}
}
return count;
}
这里通过client获取其他一个eureka server的实例信息,然后isReplication=true执行instance的注册操作
openForTraffic
Override
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {
// Renewals happen every 30 seconds and for a minute it should be a factor of 2.
this.expectedNumberOfRenewsPerMin = count * 2;
this.numberOfRenewsPerMinThreshold =
(int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());
logger.info("Got {} instances from neighboring DS node", count);
logger.info("Renew threshold is: {}", numberOfRenewsPerMinThreshold);
this.startupTime = System.currentTimeMillis();
if (count > 0) {
this.peerInstancesTransferEmptyOnStartup = false;
}
DataCenterInfo.Name selfName = applicationInfoManager.getInfo().getDataCenterInfo().getName();
boolean isAws = Name.Amazon == selfName;
if (isAws && serverConfig.shouldPrimeAwsReplicaConnections()) {
logger.info("Priming AWS connections for all replicas..");
primeAwsReplicas(applicationInfoManager);
}
logger.info("Changing status to UP");
applicationInfoManager.setInstanceStatus(InstanceStatus.UP);
super.postInit();
}
openForTraffic主要是把自身(eureka server
)标识为UP状态,然后可以开始接收请求。
eurekaServerBootstrap.contextDestroyed
public void contextDestroyed(ServletContext context) {
try {
log.info("Shutting down Eureka Server..");
context.removeAttribute(EurekaServerContext.class.getName());
destroyEurekaServerContext();
destroyEurekaEnvironment();
}
catch (Throwable e) {
log.error("Error shutting down eureka", e);
}
log.info("Eureka Service is now shutdown...");
}
/**
* Server context shutdown hook. Override for custom logic
*/
protected void destroyEurekaServerContext() throws Exception {
EurekaMonitors.shutdown();
if (this.awsBinder != null) {
this.awsBinder.shutdown();
}
if (this.serverContext != null) {
this.serverContext.shutdown();
}
}
这里销毁上下文和环境变量,注意这里有个this.serverContext != null判断,也就是如果serverContext已经被销毁了,那就不会再调用了。
小结
EurekaServerInitializerConfiguration主要是实现了Lifecycle方法,初始化servlet相关上下文,在start的时候调用EurekaServerBootstrap.contextInitialized,在stop的时候调用eurekaServerBootstrap.contextDestroyed,都是借助eurekaServerBootstrap类来实现。而eurekaServerBootstrap里头部分调用了EurekaServerContext。
EurekaServerBootstrap.contextInitialized这里有两个重要的动作registry.syncUp()以及registry.openForTraffic
- registry.syncUp()从其他eureka server获取实例信息,然后注册到本server,然后复制到其他server
- registry.openForTraffic()标识自身server的状态为UP,表示可以开始接收请求
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。