1. Eureka服务端的启动过程
1.1 入口类EurekaServerInitializerConfiguration类,
public void start() {
(new Thread(new Runnable() {
public void run() {
try {
EurekaServerInitializerConfiguration.this.eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
EurekaServerInitializerConfiguration.log.info("Started Eureka Server");
EurekaServerInitializerConfiguration.this.publish(new EurekaRegistryAvailableEvent(EurekaServerInitializerConfiguration.this.getEurekaServerConfig()));
EurekaServerInitializerConfiguration.this.running = true;
EurekaServerInitializerConfiguration.this.publish(new EurekaServerStartedEvent(EurekaServerInitializerConfiguration.this.getEurekaServerConfig()));
} catch (Exception var2) {
EurekaServerInitializerConfiguration.log.error("Could not initialize Eureka servlet context", var2);
}
}
})).start();
}
通过start()方法来加载上下文和相关的Server端的配置信息,该类上面使用了@Configuration注解,会被spring bean容器感知到。
2. Eureka的初始化
EurekaServerBootstrap类的contextInitialized方法
public void contextInitialized(ServletContext context) {
try {
this.initEurekaEnvironment(); //环境初始化
this.initEurekaServerContext(); //服务初始化
context.setAttribute(EurekaServerContext.class.getName(), this.serverContext);
} catch (Throwable var3) {
log.error("Cannot bootstrap eureka server :", var3);
throw new RuntimeException("Cannot bootstrap eureka server :", var3);
}
}
查找服务初始化中的Evicetion
protected void initEurekaServerContext() throws Exception {
JsonXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), 10000);
XmlXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), 10000);
if (this.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");
int registryCount = this.registry.syncUp();
this.registry.openForTraffic(this.applicationInfoManager, registryCount);
EurekaMonitors.registerAllStats();
}
openForTraffic()
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {
this.expectedNumberOfRenewsPerMin = count * 2;
this.numberOfRenewsPerMinThreshold = (int)((double)this.expectedNumberOfRenewsPerMin * this.serverConfig.getRenewalPercentThreshold());
logger.info("Got {} instances from neighboring DS node", count);
logger.info("Renew threshold is: {}", this.numberOfRenewsPerMinThreshold);
this.startupTime = System.currentTimeMillis();
if (count > 0) {
this.peerInstancesTransferEmptyOnStartup = false;
}
Name selfName = applicationInfoManager.getInfo().getDataCenterInfo().getName();
boolean isAws = Name.Amazon == selfName;
if (isAws && this.serverConfig.shouldPrimeAwsReplicaConnections()) {
logger.info("Priming AWS connections for all replicas..");
this.primeAwsReplicas(applicationInfoManager);
}
logger.info("Changing status to UP");
applicationInfoManager.setInstanceStatus(InstanceStatus.UP);
super.postInit();
}
protected void postInit() {
this.renewsLastMin.start();
if (this.evictionTaskRef.get() != null) {
((AbstractInstanceRegistry.EvictionTask)this.evictionTaskRef.get()).cancel();
}
this.evictionTaskRef.set(new AbstractInstanceRegistry.EvictionTask());
this.evictionTimer.schedule((TimerTask)this.evictionTaskRef.get(), this.serverConfig.getEvictionIntervalTimerInMs(), this.serverConfig.getEvictionIntervalTimerInMs());
}
2. 客户端注册过程
客户端流程
1.入口:DiscoveryClient功能描述
1) 向Eureka Server注册服务实例
2)向Eureka Server续约
3) 当服务关闭的时候向Eureka Server取消租约
4) 查询注册到Eureka Server中的服务实例
2 实例化,调用构造方法
@Inject
DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args, Provider<BackupRegistry> backupRegistryProvider) {
this.RECONCILE_HASH_CODES_MISMATCH = Monitors.newCounter("DiscoveryClient_ReconcileHashCodeMismatch");
this.FETCH_REGISTRY_TIMER = Monitors.newTimer("DiscoveryClient_FetchRegistry");
this.REREGISTER_COUNTER = Monitors.newCounter("DiscoveryClient_Reregister");
this.localRegionApps = new AtomicReference();
this.fetchRegistryUpdateLock = new ReentrantLock();
this.healthCheckHandlerRef = new AtomicReference();
this.remoteRegionVsApps = new ConcurrentHashMap();
this.lastRemoteInstanceStatus = InstanceStatus.UNKNOWN;
this.eventListeners = new CopyOnWriteArraySet();
this.registrySize = 0;
this.lastSuccessfulRegistryFetchTimestamp = -1L;
this.lastSuccessfulHeartbeatTimestamp = -1L;
this.isShutdown = new AtomicBoolean(false);
if (args != null) {
this.healthCheckHandlerProvider = args.healthCheckHandlerProvider;
this.healthCheckCallbackProvider = args.healthCheckCallbackProvider;
this.eventListeners.addAll(args.getEventListeners());
this.preRegistrationHandler = args.preRegistrationHandler;
} else {
this.healthCheckCallbackProvider = null;
this.healthCheckHandlerProvider = null;
this.preRegistrationHandler = null;
}
this.applicationInfoManager = applicationInfoManager;
InstanceInfo myInfo = applicationInfoManager.getInfo();
this.clientConfig = config;
staticClientConfig = this.clientConfig;
this.transportConfig = config.getTransportConfig();
this.instanceInfo = myInfo;
if (myInfo != null) {
this.appPathIdentifier = this.instanceInfo.getAppName() + "/" + this.instanceInfo.getId();
} else {
logger.warn("Setting instanceInfo to a passed in null value");
}
this.backupRegistryProvider = backupRegistryProvider;
this.urlRandomizer = new InstanceInfoBasedUrlRandomizer(this.instanceInfo);
this.localRegionApps.set(new Applications());
this.fetchRegistryGeneration = new AtomicLong(0L);
this.remoteRegionsToFetch = new AtomicReference(this.clientConfig.fetchRegistryForRemoteRegions());
this.remoteRegionsRef = new AtomicReference(this.remoteRegionsToFetch.get() == null ? null : ((String)this.remoteRegionsToFetch.get()).split(","));
if (config.shouldFetchRegistry()) {
this.registryStalenessMonitor = new ThresholdLevelsMetric(this, "eurekaClient.registry.lastUpdateSec_", new long[]{15L, 30L, 60L, 120L, 240L, 480L});
} else {
this.registryStalenessMonitor = ThresholdLevelsMetric.NO_OP_METRIC;
}
if (config.shouldRegisterWithEureka()) {
this.heartbeatStalenessMonitor = new ThresholdLevelsMetric(this, "eurekaClient.registration.lastHeartbeatSec_", new long[]{15L, 30L, 60L, 120L, 240L, 480L});
} else {
this.heartbeatStalenessMonitor = ThresholdLevelsMetric.NO_OP_METRIC;
}
logger.info("Initializing Eureka in region {}", this.clientConfig.getRegion());
if (!config.shouldRegisterWithEureka() && !config.shouldFetchRegistry()) {
logger.info("Client configured to neither register nor query for data.");
this.scheduler = null;
this.heartbeatExecutor = null;
this.cacheRefreshExecutor = null;
this.eurekaTransport = null;
this.instanceRegionChecker = new InstanceRegionChecker(new PropertyBasedAzToRegionMapper(config), this.clientConfig.getRegion());
DiscoveryManager.getInstance().setDiscoveryClient(this);
DiscoveryManager.getInstance().setEurekaClientConfig(config);
this.initTimestampMs = System.currentTimeMillis();
logger.info("Discovery Client initialized at timestamp {} with initial instances count: {}", this.initTimestampMs, this.getApplications().size());
} else {
try {
this.scheduler = Executors.newScheduledThreadPool(2, (new ThreadFactoryBuilder()).setNameFormat("DiscoveryClient-%d").setDaemon(true).build());
this.heartbeatExecutor = new ThreadPoolExecutor(1, this.clientConfig.getHeartbeatExecutorThreadPoolSize(), 0L, TimeUnit.SECONDS, new SynchronousQueue(), (new ThreadFactoryBuilder()).setNameFormat("DiscoveryClient-HeartbeatExecutor-%d").setDaemon(true).build());
this.cacheRefreshExecutor = new ThreadPoolExecutor(1, this.clientConfig.getCacheRefreshExecutorThreadPoolSize(), 0L, TimeUnit.SECONDS, new SynchronousQueue(), (new ThreadFactoryBuilder()).setNameFormat("DiscoveryClient-CacheRefreshExecutor-%d").setDaemon(true).build());
this.eurekaTransport = new DiscoveryClient.EurekaTransport();
this.scheduleServerEndpointTask(this.eurekaTransport, args);
Object azToRegionMapper;
if (this.clientConfig.shouldUseDnsForFetchingServiceUrls()) {
azToRegionMapper = new DNSBasedAzToRegionMapper(this.clientConfig);
} else {
azToRegionMapper = new PropertyBasedAzToRegionMapper(this.clientConfig);
}
if (null != this.remoteRegionsToFetch.get()) {
((AzToRegionMapper)azToRegionMapper).setRegionsToFetch(((String)this.remoteRegionsToFetch.get()).split(","));
}
this.instanceRegionChecker = new InstanceRegionChecker((AzToRegionMapper)azToRegionMapper, this.clientConfig.getRegion());
} catch (Throwable var9) {
throw new RuntimeException("Failed to initialize DiscoveryClient!", var9);
}
if (this.clientConfig.shouldFetchRegistry() && !this.fetchRegistry(false)) {
this.fetchRegistryFromBackup();
}
if (this.preRegistrationHandler != null) {
this.preRegistrationHandler.beforeRegistration();
}
if (this.clientConfig.shouldRegisterWithEureka() && this.clientConfig.shouldEnforceRegistrationAtInit()) {
try {
if (!this.register()) {
throw new IllegalStateException("Registration error at startup. Invalid server response.");
}
} catch (Throwable var8) {
logger.error("Registration error at startup: {}", var8.getMessage());
throw new IllegalStateException(var8);
}
}
this.initScheduledTasks(); //注册任务主要是在这个定时任务里面实现
try {
Monitors.registerObject(this);
}