注册、心跳、下线、剔除、获取注册表、集群同步
1.EurekaServerAutoConfiguration
实例化EurekaServerConfigBean
@Configuration(proxyBeanMethods = false)
protected static class EurekaServerConfigBeanConfiguration {
@Bean
@ConditionalOnMissingBean
public EurekaServerConfig eurekaServerConfig(EurekaClientConfig clientConfig) {
EurekaServerConfigBean server = new EurekaServerConfigBean();
// eureka.client.register-with-eureka
if (clientConfig.shouldRegisterWithEureka()) {
// Set a sensible default if we are supposed to replicate
server.setRegistrySyncRetries(5);
}
return server;
}
}
Application
@Bean
public javax.ws.rs.core.Application jerseyApplication(Environment environment,
ResourceLoader resourceLoader) {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(
false, environment);
provider.addIncludeFilter(new AnnotationTypeFilter(Path.class));
provider.addIncludeFilter(new AnnotationTypeFilter(Provider.class));
Set<Class<?>> classes = new HashSet<>();
// 扫描bean, 包含8个Resource
for (String basePackage : EUREKA_PACKAGES) {
Set<BeanDefinition> beans = provider.findCandidateComponents(basePackage);
for (BeanDefinition bd : beans) {
Class<?> cls = ClassUtils.resolveClassName(bd.getBeanClassName(),
resourceLoader.getClassLoader());
classes.add(cls);
}
}
Map<String, Object> propsAndFeatures = new HashMap<>();
propsAndFeatures.put(
// Skip static content used by the webapp
ServletContainer.PROPERTY_WEB_PAGE_CONTENT_REGEX,
EurekaConstants.DEFAULT_PREFIX + "/(fonts|images|css|js)/.*");
DefaultResourceConfig rc = new DefaultResourceConfig(classes);
rc.setPropertiesAndFeatures(propsAndFeatures);
return rc;
}
实例化PeerAwareInstanceRegistry:
@Bean
public PeerAwareInstanceRegistry peerAwareInstanceRegistry(
ServerCodecs serverCodecs) {
this.eurekaClient.getApplications(); // force initialization
// 实例化一个registry对象
return new InstanceRegistry(this.eurekaServerConfig, this.eurekaClientConfig,
serverCodecs, this.eurekaClient,
this.instanceRegistryProperties.getExpectedNumberOfClientsSendingRenews(),
this.instanceRegistryProperties.getDefaultOpenForTrafficCount());
}
//serverConfig服务端配置,clientConfig客户端配置,
public InstanceRegistry(EurekaServerConfig serverConfig,
EurekaClientConfig clientConfig, ServerCodecs serverCodecs,
EurekaClient eurekaClient, int expectedNumberOfClientsSendingRenews,
int defaultOpenForTrafficCount) {
// 实例化父类PeerAwareInstanceRegistryImpl
super(serverConfig, clientConfig, serverCodecs, eurekaClient);
this.expectedNumberOfClientsSendingRenews = expectedNumberOfClientsSendingRenews;
this.defaultOpenForTrafficCount = defaultOpenForTrafficCount;
}
@Inject
public PeerAwareInstanceRegistryImpl(EurekaServerConfig serverConfig, EurekaClientConfig clientConfig, ServerCodecs serverCodecs, EurekaClient eurekaClient) {
// 实例化父类AbstractInstanceRegistry
super(serverConfig, clientConfig, serverCodecs);
this.eurekaClient = eurekaClient;
this.numberOfReplicationsLastMin = new MeasuredRate(60000L);
this.instanceStatusOverrideRule =
new FirstMatchWinsCompositeRule(
new InstanceStatusOverrideRule[]{new DownOrStartingRule(),
new OverrideExistsRule(this.overriddenInstanceStatusMap),
new LeaseExistsRule()
}
);
}
protected AbstractInstanceRegistry(EurekaServerConfig serverConfig, EurekaClientConfig clientConfig, ServerCodecs serverCodecs) {
this.overriddenInstanceStatusMap =
CacheBuilder.newBuilder().initialCapacity(500).expireAfterAccess(1L,TimeUnit.HOURS).build().asMap();
// 最近改变的队列
this.recentlyChangedQueue = new ConcurrentLinkedQueue();
this.readWriteLock = new ReentrantReadWriteLock();
this.read = this.readWriteLock.readLock();
this.write = this.readWriteLock.writeLock();
this.lock = new Object();
// 保留三分钟内的注册信息
this.deltaRetentionTimer = new Timer("Eureka-DeltaRetentionTimer", true);
// 剔除任务
this.evictionTimer = new Timer("Eureka-EvictionTimer", true);
this.evictionTaskRef = new AtomicReference();
this.allKnownRemoteRegions = EMPTY_STR_ARRAY;
this.serverConfig = serverConfig;
this.clientConfig = clientConfig;
this.serverCodecs = serverCodecs;
this.recentCanceledQueue = new AbstractInstanceRegistry.CircularQueue(1000);
this.recentRegisteredQueue = new AbstractInstanceRegistry.CircularQueue(1000);
// 每一分钟初始化续约次数
this.renewsLastMin = new MeasuredRate(60000L);
// 定时任务,默认每三十秒执行一次,如果3分钟之内没有更新过就从recentlyChangedQueue队列移除
this.deltaRetentionTimer.schedule(this.getDeltaRetentionTask(),
serverConfig.getDeltaRetentionTimerIntervalInMs(),
serverConfig.getDeltaRetentionTimerIntervalInMs());
}
private TimerTask getDeltaRetentionTask() {
return new TimerTask() {
public void run() {
Iterator it = AbstractInstanceRegistry.this.recentlyChangedQueue.iterator();
while(it.hasNext() &&
// (当前时间 - 最后更新时间)> 服务端配置的保留时间
((AbstractInstanceRegistry.RecentlyChangedItem)it.next()).getLastUpdateTime() < System.currentTimeMillis() - AbstractInstanceRegistry.this.serverConfig.getRetentionTimeInMSInDeltaQueue()) {
it.remove();
}
}
};
}
实例化PeerEurekaNodes
@Bean
@ConditionalOnMissingBean
public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry,
ServerCodecs serverCodecs,
ReplicationClientAdditionalFilters replicationClientAdditionalFilters) {
return new RefreshablePeerEurekaNodes(registry,
this.eurekaServerConfig,
this.eurekaClientConfig,
serverCodecs,
this.applicationInfoManager,
replicationClientAdditionalFilters);
}
RefreshablePeerEurekaNodes(final PeerAwareInstanceRegistry registry,
final EurekaServerConfig serverConfig,
final EurekaClientConfig clientConfig, final ServerCodecs serverCodecs,
final ApplicationInfoManager applicationInfoManager,
final ReplicationClientAdditionalFilters replicationClientAdditionalFilters) {
// 实例化父类PeerEurekaNodes
super(registry, serverConfig, clientConfig, serverCodecs,applicationInfoManager);
this.replicationClientAdditionalFilters = replicationClientAdditionalFilters;
}
@Inject
public PeerEurekaNodes(PeerAwareInstanceRegistry registry,
EurekaServerConfig serverConfig,
EurekaClientConfig clientConfig,
ServerCodecs serverCodecs,
ApplicationInfoManager applicationInfoManager) {
this.registry = registry;
this.serverConfig = serverConfig;
this.clientConfig = clientConfig;
this.serverCodecs = serverCodecs;
this.applicationInfoManager = applicationInfoManager;
}
实例化EurekaServerContext
@Bean
@ConditionalOnMissingBean
public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs,
PeerAwareInstanceRegistry registry,
PeerEurekaNodes peerEurekaNodes) {
return new DefaultEurekaServerContext(this.eurekaServerConfig,
serverCodecs,
registry,
peerEurekaNodes,
this.applicationInfoManager);
}
// DefaultEurekaServerContext
@Inject
public DefaultEurekaServerContext(EurekaServerConfig serverConfig,
ServerCodecs serverCodecs,
PeerAwareInstanceRegistry registry,
PeerEurekaNodes peerEurekaNodes,
ApplicationInfoManager applicationInfoManager) {
this.serverConfig = serverConfig;
this.serverCodecs = serverCodecs;
this.registry = registry;
this.peerEurekaNodes = peerEurekaNodes;
this.applicationInfoManager = applicationInfoManager;
}
@PostConstruct
public void initialize() {
// 更新peer
this.peerEurekaNodes.start();
try {
this.registry.init(this.peerEurekaNodes);
} catch (Exception var2) {
throw new RuntimeException(var2);
}
}
// PeerEurekaNodes
public void start() {
this.taskExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "Eureka-PeerNodesUpdater");
thread.setDaemon(true);
return thread;
}
});
try {
// 更新peer, 默认10分钟执行一次
this.updatePeerEurekaNodes(this.resolvePeerUrls());
// 更新peer, 默认10分钟执行一次
Runnable peersUpdateTask = new Runnable() {
public void run() {
try {
PeerEurekaNodes.this.updatePeerEurekaNodes(PeerEurekaNodes.this.resolvePeerUrls());
} catch (Throwable var2) {
PeerEurekaNodes.logger.error("Cannot update the replica Nodes", var2);
}
}
};
this.taskExecutor.scheduleWithFixedDelay(peersUpdateTask,
(long)this.serverConfig.getPeerEurekaNodesUpdateIntervalMs(),
(long)this.serverConfig.getPeerEurekaNodesUpdateIntervalMs(),
TimeUnit.MILLISECONDS);
} catch (Exception var3) {
throw new IllegalStateException(var3);
}
Iterator var4 = this.peerEurekaNodes.iterator();
while(var4.hasNext()) {
PeerEurekaNode node = (PeerEurekaNode)var4.next();
}
}
protected void updatePeerEurekaNodes(List<String> newPeerUrls) {
if (newPeerUrls.isEmpty()) {
logger.warn("The replica size seems to be empty. Check the route 53 DNS Registry");
} else {
// 同步节点, 比如已经注册的节点有 1 2 3,本次注册的节点是 2 3 4
// toShautdown 包括 1,toadd 包括 4,然后关闭节点1 同时注册节点4
Set<String> toShutdown = new HashSet(this.peerEurekaNodeUrls);
toShutdown.removeAll(newPeerUrls);
Set<String> toAdd = new HashSet(newPeerUrls);
toAdd.removeAll(this.peerEurekaNodeUrls);
if (!toShutdown.isEmpty() || !toAdd.isEmpty()) {
List<PeerEurekaNode> newNodeList = new ArrayList(this.peerEurekaNodes);
if (!toShutdown.isEmpty()) {
int i = 0;
while(i < newNodeList.size()) {
PeerEurekaNode eurekaNode = (PeerEurekaNode)newNodeList.get(i);
if (toShutdown.contains(eurekaNode.getServiceUrl())) {
newNodeList.remove(i);
eurekaNode.shutDown();
} else {
++i;
}
}
}
if (!toAdd.isEmpty()) {
logger.info("Adding new peer nodes {}", toAdd);
Iterator var7 = toAdd.iterator();
while(var7.hasNext()) {
String peerUrl = (String)var7.next();
newNodeList.add(this.createPeerEurekaNode(peerUrl));
}
}
this.peerEurekaNodes = newNodeList;
this.peerEurekaNodeUrls = new HashSet(newPeerUrls);
}
}
}
PeerAwareInstanceRegistryImpl
public void init(PeerEurekaNodes peerEurekaNodes) throws Exception {
this.numberOfReplicationsLastMin.start();
this.peerEurekaNodes = peerEurekaNodes;
// 初始化缓存
this.initializedResponseCache();
// 15分钟执行一次
this.scheduleRenewalThresholdUpdateTask();
this.initRemoteRegionRegistry();
try {
Monitors.registerObject(this);
} catch (Throwable var3) {
}
}
public synchronized void initializedResponseCache() {
if (this.responseCache == null) {
this.responseCache = new ResponseCacheImpl(this.serverConfig, this.serverCodecs, this);
}
}
private void scheduleRenewalThresholdUpdateTask() {
this.timer.schedule(new TimerTask() {
public void run() {
PeerAwareInstanceRegistryImpl.this.updateRenewalThreshold();
}
}, (long)this.serverConfig.getRenewalThresholdUpdateIntervalMs(),
(long)this.serverConfig.getRenewalThresholdUpdateIntervalMs());
}
private void updateRenewalThreshold() {
try {
Applications apps = this.eurekaClient.getApplications();
int count = 0;
Iterator var3 = apps.getRegisteredApplications().iterator();
while(var3.hasNext()) {
Application app = (Application)var3.next();
Iterator var5 = app.getInstances().iterator();
while(var5.hasNext()) {
InstanceInfo instance = (InstanceInfo)var5.next();
if (this.isRegisterable(instance)) {
++count;
}
}
}
Object var10 = this.lock;
synchronized(this.lock) {
if ((double)count > this.serverConfig.getRenewalPercentThreshold() * (double)this.expectedNumberOfClientsSendingRenews || !this.isSelfPreservationModeEnabled()) {
this.expectedNumberOfClientsSendingRenews = count;
this.updateRenewsPerMinThreshold();
}
}
} catch (Throwable var9) {
}
}
// 更新阈值
protected void updateRenewsPerMinThreshold() {
this.numberOfRenewsPerMinThreshold = (int)((double)this.expectedNumberOfClientsSendingRenews * (60.0D / (double)this.serverConfig.getExpectedClientRenewalIntervalSeconds()) * this.serverConfig.getRenewalPercentThreshold());
}
ResponseCacheImpl
ResponseCacheImpl(EurekaServerConfig serverConfig, ServerCodecs serverCodecs, AbstractInstanceRegistry registry) {
this.serverConfig = serverConfig;
this.serverCodecs = serverCodecs;
this.shouldUseReadOnlyResponseCache = serverConfig.shouldUseReadOnlyResponseCache();
this.registry = registry;
long responseCacheUpdateIntervalMs = serverConfig.getResponseCacheUpdateIntervalMs();
// 初始化一个容量1000的二级缓存
this.readWriteCacheMap = CacheBuilder.newBuilder()
.initialCapacity(serverConfig.getInitialCapacityOfResponseCache())
.expireAfterWrite(serverConfig.getResponseCacheAutoExpirationInSeconds(), TimeUnit.SECONDS).removalListener(new RemovalListener<Key, ResponseCacheImpl.Value>() {
public void onRemoval(RemovalNotification<Key, ResponseCacheImpl.Value> notification) {
Key removedKey = (Key)notification.getKey();
if (removedKey.hasRegions()) {
Key cloneWithNoRegions = removedKey.cloneWithoutRegions();
ResponseCacheImpl.this.regionSpecificKeys.remove(cloneWithNoRegions, removedKey);
}
}
}).build(new CacheLoader<Key, ResponseCacheImpl.Value>() {
// 如果缓存(readWriteCacheMap)中不存在就调用该方法获取值
public ResponseCacheImpl.Value load(Key key) throws Exception {
if (key.hasRegions()) {
Key cloneWithNoRegions = key.cloneWithoutRegions();
ResponseCacheImpl.this.regionSpecificKeys.put(cloneWithNoRegions, key);
}
// 主要逻辑
ResponseCacheImpl.Value value = ResponseCacheImpl.this.generatePayload(key);
return value;
}
});
// 如果使用三级缓存,定时同步二级缓存的数据到三级缓存,默认三十秒同步一次
if (this.shouldUseReadOnlyResponseCache) {
this.timer.schedule(this.getCacheUpdateTask(),
new Date(System.currentTimeMillis() / responseCacheUpdateIntervalMs * responseCacheUpdateIntervalMs + responseCacheUpdateIntervalMs),
responseCacheUpdateIntervalMs);
}
try {
Monitors.registerObject(this);
} catch (Throwable var7) {
}
}
private TimerTask getCacheUpdateTask() {
return new TimerTask() {
public void run() {
Iterator var1 = ResponseCacheImpl.this.readOnlyCacheMap.keySet().iterator();
while(var1.hasNext()) {
Key key = (Key)var1.next();
try {
CurrentRequestVersion.set(key.getVersion());
// 二级缓存中的值
ResponseCacheImpl.Value cacheValue = (ResponseCacheImpl.Value)ResponseCacheImpl.readWriteCacheMap.get(key);
// 三级缓存中的值
ResponseCacheImpl.Value currentCache = (ResponseCacheImpl.Value)ResponseCacheImpl.readOnlyCacheMap.get(key);
if (cacheValue != currentCacheValue) {
ResponseCacheImpl.this.readOnlyCacheMap.put(key, cacheValue);
}
} catch (Throwable var8) {
} finally {
CurrentRequestVersion.remove();
}
}
}
};
}
private ResponseCacheImpl.Value generatePayload(Key key) {
Stopwatch tracer = null;
ResponseCacheImpl.Value var8;
try {
String payload;
switch(key.getEntityType()) {
case Application:
boolean isRemoteRegionRequested = key.hasRegions();
if ("ALL_APPS".equals(key.getName())) {// 如果是全量则从一级缓存中拿
if (isRemoteRegionRequested) {
tracer = this.serializeAllAppsWithRemoteRegionTimer.start();
payload = this.getPayLoad(key, this.registry.getApplicationsFromMultipleRegions(key.getRegions()));
} else {
tracer = this.serializeAllAppsTimer.start();
payload = this.getPayLoad(key, this.registry.getApplications());
}
} else if ("ALL_APPS_DELTA".equals(key.getName())) {// 如果是增量则从recentlyChangedQueue中拿
if (isRemoteRegionRequested) {
tracer = this.serializeDeltaAppsWithRemoteRegionTimer.start();
this.versionDeltaWithRegions.incrementAndGet();
versionDeltaWithRegionsLegacy.incrementAndGet();
payload = this.getPayLoad(key, this.registry.getApplicationDeltasFromMultipleRegions(key.getRegions()));
} else {
tracer = this.serializeDeltaAppsTimer.start();
this.versionDelta.incrementAndGet();
versionDeltaLegacy.incrementAndGet();
payload = this.getPayLoad(key, this.registry.getApplicationDeltas());
}
} else {// 从一级缓存中拿
tracer = this.serializeOneApptimer.start();
payload = this.getPayLoad(key, this.registry.getApplication(key.getName()));
}
break;
case VIP:
case SVIP:
tracer = this.serializeViptimer.start();
payload = this.getPayLoad(key, getApplicationsForVip(key, this.registry));
break;
default:
payload = "";
}
var8 = new ResponseCacheImpl.Value(payload);
} finally {
if (tracer != null) {
tracer.stop();
}
}
return var8;
}
AbstractInstanceRegistry
protected void initRemoteRegionRegistry() throws MalformedURLException {
Map<String, String> remoteRegionUrlsWithName = this.serverConfig.getRemoteRegionUrlsWithName();
if (!remoteRegionUrlsWithName.isEmpty()) {
this.allKnownRemoteRegions = new String[remoteRegionUrlsWithName.size()];
int remoteRegionArrayIndex = 0;
Entry remoteRegionUrlWithName;
for(Iterator var3 = remoteRegionUrlsWithName.entrySet().iterator();
var3.hasNext();
this.allKnownRemoteRegions[remoteRegionArrayIndex++] = (String)remoteRegionUrlWithName.getKey()) {
remoteRegionUrlWithName = (Entry)var3.next();
RemoteRegionRegistry remoteRegionRegistry =
new RemoteRegionRegistry(this.serverConfig, this.clientConfig, this.serverCodecs,
(String)remoteRegionUrlWithName.getKey(),
new URL((String)remoteRegionUrlWithName.getValue()));
this.regionNameVSRemoteRegistry.put(remoteRegionUrlWithName.getKey(), remoteRegionRegistry);
}
}
}
实例化EurekaServerBootstrap
@Bean
public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,
EurekaServerContext serverContext) {
return new EurekaServerBootstrap(this.applicationInfoManager,
this.eurekaClientConfig,
this.eurekaServerConfig,
registry,
serverContext);
}
2.EurekaServerInitializerConfiguration
通过EurekaServerAutoConfiguration的@Import导入
@Configuration(proxyBeanMethods = false)
@Import(EurekaServerInitializerConfiguration.class)
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
实现接口SmartLifecycle接口,springboot启动会自动执行start方法
@Configuration(proxyBeanMethods = false)
public class EurekaServerInitializerConfiguration
implements ServletContextAware, SmartLifecycle, Ordered {}
@Override
public void start() {
new Thread(() -> {
try {
// 初始化eureka环境和同步
eurekaServerBootstrap.contextInitialized(
EurekaServerInitializerConfiguration.this.servletContext);
publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
EurekaServerInitializerConfiguration.this.running = true;
publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
}
catch (Exception ex) {
}
}).start();
}
public void contextInitialized(ServletContext context) {
try {
// 初始化eureka环境
initEurekaEnvironment();
// 表面意思初始化eureka上下文
initEurekaServerContext();
context.setAttribute(EurekaServerContext.class.getName(), this.serverContext);
}
catch (Throwable e) {
}
}
protected void initEurekaServerContext() throws Exception {
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对象,设置一个serverContext
EurekaServerContextHolder.initialize(this.serverContext);
int registryCount = this.registry.syncUp();
this.registry.openForTraffic(this.applicationInfoManager, registryCount);
EurekaMonitors.registerAllStats();
}
PeerAwareInstanceRegistryImpl
public int syncUp() {
int count = 0;
// this.serverConfig.getRegistrySyncRetries() 根据配置决定eureka.client.register-with-eureka
// 如果配置的true,则默认是五次,如果设置false则只有一次
for(int i = 0; i < this.serverConfig.getRegistrySyncRetries() && count == 0; ++i) {
if (i > 0) {
try {
// 默认30s
Thread.sleep(this.serverConfig.getRegistrySyncRetryWaitMs());
} catch (InterruptedException var10) {
logger.warn("Interrupted during registry transfer..");
break;
}
}
// 获取所有的服务列表,根据注册到eureka上的spring.application.name,一个服务可以有多个实例
Applications apps = this.eurekaClient.getApplications();
Iterator var4 = apps.getRegisteredApplications().iterator();
while(var4.hasNext()) {
Application app = (Application)var4.next();
Iterator var6 = app.getInstances().iterator();
while(var6.hasNext()) {
InstanceInfo instance = (InstanceInfo)var6.next();
try {
// 判断是否可以注册,一般都可以注册,除非数据中心DataCenterInfo是AmazonInfo
if (this.isRegisterable(instance)) {
// 注册
this.register(instance, instance.getLeaseInfo().getDurationInSecs(), true);
++count;
}
} catch (Throwable var9) {
logger.error("During DS init copy", var9);
}
}
}
}
return count;
}
InstanceRegistry
@Override
public void register(InstanceInfo info, int leaseDuration, boolean isReplication) {
// 发布服务注册事件
handleRegistration(info, leaseDuration, isReplication);
super.register(info, leaseDuration, isReplication);
}
AbstractInstanceRegistry
public void register(InstanceInfo registrant, int leaseDuration, boolean isReplication) {
try {
this.read.lock();
// 根据实例的服务名称获取当前服务的的所有实例
Map<String, Lease<InstanceInfo>> gMap = (Map)this.registry.get(registrant.getAppName());
EurekaMonitors.REGISTER.increment(isReplication);
if (gMap == null) {
ConcurrentHashMap<String, Lease<InstanceInfo>> gNewMap = new ConcurrentHashMap();
gMap = (Map)this.registry.putIfAbsent(registrant.getAppName(), gNewMap);
if (gMap == null) {
gMap = gNewMap;
}
}
// 获取实例的信息
Lease<InstanceInfo> existingLease = (Lease)((Map)gMap).get(registrant.getId());
if (existingLease != null && existingLease.getHolder() != null) {
Long existingLastDirtyTimestamp =
((InstanceInfo)existingLease.getHolder()).getLastDirtyTimestamp();
Long registrationLastDirtyTimestamp = registrant.getLastDirtyTimestamp();
if (existingLastDirtyTimestamp > registrationLastDirtyTimestamp) {
registrant = (InstanceInfo)existingLease.getHolder();
}
} else {
Object var6 = this.lock;
synchronized(this.lock) {
if (this.expectedNumberOfClientsSendingRenews > 0) {
++this.expectedNumberOfClientsSendingRenews;
this.updateRenewsPerMinThreshold();
}
}
}
// 封装实例信息
Lease<InstanceInfo> lease = new Lease(registrant, leaseDuration);
if (existingLease != null) {
lease.setServiceUpTimestamp(existingLease.getServiceUpTimestamp());
}
// 缓存实例信息
((Map)gMap).put(registrant.getId(), lease);
// 加到最近注册的队列
this.recentRegisteredQueue.add(
new Pair(System.currentTimeMillis(), registrant.getAppName() + "(" + registrant.getId() + ")"));
if (!InstanceStatus.UNKNOWN.equals(registrant.getOverriddenStatus())) {
if (!this.overriddenInstanceStatusMap.containsKey(registrant.getId())) {
this.overriddenInstanceStatusMap.put(registrant.getId(), registrant.getOverriddenStatus());
}
}
InstanceStatus overriddenStatusFromMap =
(InstanceStatus)this.overriddenInstanceStatusMap.get(registrant.getId());
if (overriddenStatusFromMap != null) {
registrant.setOverriddenStatus(overriddenStatusFromMap);
}
InstanceStatus overriddenInstanceStatus =
this.getOverriddenInstanceStatus(registrant, existingLease, isReplication);
registrant.setStatusWithoutDirty(overriddenInstanceStatus);
if (InstanceStatus.UP.equals(registrant.getStatus())) {
lease.serviceUp();
}
registrant.setActionType(ActionType.ADDED);
// 加到最近改变的队列
this.recentlyChangedQueue.add(new AbstractInstanceRegistry.RecentlyChangedItem(lease));
// 设置最后更新时间
registrant.setLastUpdatedTimestamp();
// 缓存失效,从readWriteCacheMap中删除
this.invalidateCache(registrant.getAppName(),
registrant.getVIPAddress(),
registrant.getSecureVipAddress());
} finally {
this.read.unlock();
}
}
InstanceRegistry
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {
// defaultOpenForTrafficCount默认是1
super.openForTraffic(applicationInfoManager, count == 0 ? this.defaultOpenForTrafficCount : count);
}
PeerAwareInstanceRegistryImpl
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {
// 期望续约的客户端的数量
this.expectedNumberOfClientsSendingRenews = count;
// 续约的阈值 (int)((double)this.expectedNumberOfClientsSendingRenews *
// (60.0D / (double)this.serverConfig.getExpectedClientRenewalIntervalSeconds()) *
// this.serverConfig.getRenewalPercentThreshold());
// this.serverConfig.getExpectedClientRenewalIntervalSeconds()期望的客户端续约的间隔时间,默认30s
// eureka.server.expected-client-renewal-interval-seconds
// this.serverConfig.getRenewalPercentThreshold()开启自我保护的阈值,默认0.85
// eureka.server.renewal-percent-threshold
// 每分钟续约的阈值==(int)(期望续约的客户端数量 * (60s / 续约间隔时间) * 续约的阈值)
this.updateRenewsPerMinThreshold();
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()) {
this.primeAwsReplicas(applicationInfoManager);
}
// 设置服务的状态为UP
applicationInfoManager.setInstanceStatus(InstanceStatus.UP);
super.postInit();
}
AbstractInstanceRegistry
protected void postInit() {
this.renewsLastMin.start();
if (this.evictionTaskRef.get() != null) {
// 当前存在服务剔除任务则取消任务
((AbstractInstanceRegistry.EvictionTask)this.evictionTaskRef.get()).cancel();
}
// 设置服务剔除任务
this.evictionTaskRef.set(new AbstractInstanceRegistry.EvictionTask());
// 启动服务剔除任务,this.serverConfig.getEvictionIntervalTimerInMs()剔除服务的时间间隔
// eureka.server.eviction-interval-timer-in-ms,时间可以设置小一点,让无效服务快速下线
this.evictionTimer.schedule((TimerTask)this.evictionTaskRef.get(),
this.serverConfig.getEvictionIntervalTimerInMs(),
this.serverConfig.getEvictionIntervalTimerInMs());
}
class EvictionTask extends TimerTask {
...
public void run() {
try {
long compensationTimeMs = this.getCompensationTimeMs();
// 剔除逻辑
AbstractInstanceRegistry.this.evict(compensationTimeMs);
} catch (Throwable var3) {
AbstractInstanceRegistry.logger.error("Could not run the evict task", var3);
}
}
...
}
public void evict(long additionalLeaseMs) {
// eureka.server.enable-self-preservation自我保护的开关
// 1.关闭自我保护会执行剔除逻辑
// 2.最后一分钟服务续约的次数大于每分钟服务续约的阈值会执行剔除逻辑
if (!this.isLeaseExpirationEnabled()) {
logger.debug("DS: lease expiration is currently disabled.");
} else {
List<Lease<InstanceInfo>> expiredLeases = new ArrayList();
Iterator var4 = this.registry.entrySet().iterator();
while(true) {
Map leaseMap;
do {
if (!var4.hasNext()) {
// 注册的服务的数量
int registrySize = (int)this.getLocalRegistrySize();
// this.serverConfig.getRenewalPercentThreshold()自我保护的阈值
// eureka.server.renewal-percent-threshold默认值0.85
int registrySizeThreshold =
(int)((double)registrySize * this.serverConfig.getRenewalPercentThreshold());
int evictionLimit = registrySize - registrySizeThreshold;
int toEvict = Math.min(expiredLeases.size(), evictionLimit);
// 达到阈值就剔除
if (toEvict > 0) {
Random random = new Random(System.currentTimeMillis());
for(int i = 0; i < toEvict; ++i) {
int next = i + random.nextInt(expiredLeases.size() - i);
Collections.swap(expiredLeases, i, next);
Lease<InstanceInfo> lease = (Lease)expiredLeases.get(i);
String appName = ((InstanceInfo)lease.getHolder()).getAppName();
String id = ((InstanceInfo)lease.getHolder()).getId();
EurekaMonitors.EXPIRED.increment();
logger.warn("DS: Registry: expired lease for {}/{}", appName, id);
this.internalCancel(appName, id, false);
}
}
return;
}
Entry<String, Map<String, Lease<InstanceInfo>>> groupEntry = (Entry)var4.next();
leaseMap = (Map)groupEntry.getValue();
} while(leaseMap == null);
Iterator var7 = leaseMap.entrySet().iterator();
while(var7.hasNext()) {
Entry<String, Lease<InstanceInfo>> leaseEntry = (Entry)var7.next();
Lease<InstanceInfo> lease = (Lease)leaseEntry.getValue();
// 如果90s内没有更新信息就加入到剔除队列
if (lease.isExpired(additionalLeaseMs) && lease.getHolder() != null) {
expiredLeases.add(lease);
}
}
}
}
}
protected boolean internalCancel(String appName, String id, boolean isReplication) {
try {
this.read.lock();
EurekaMonitors.CANCEL.increment(isReplication);
Map<String, Lease<InstanceInfo>> gMap = (Map)this.registry.get(appName);
Lease<InstanceInfo> leaseToCancel = null;
if (gMap != null) {
leaseToCancel = (Lease)gMap.remove(id);
}
this.recentCanceledQueue.add(new Pair(System.currentTimeMillis(), appName + "(" + id + ")"));
InstanceStatus instanceStatus = (InstanceStatus)this.overriddenInstanceStatusMap.remove(id);
if (leaseToCancel == null) {
EurekaMonitors.CANCEL_NOT_FOUND.increment(isReplication);
boolean var17 = false;
return var17;
}
leaseToCancel.cancel();
InstanceInfo instanceInfo = (InstanceInfo)leaseToCancel.getHolder();
String vip = null;
String svip = null;
if (instanceInfo != null) {
instanceInfo.setActionType(ActionType.DELETED);
this.recentlyChangedQueue.add(new AbstractInstanceRegistry.RecentlyChangedItem(leaseToCancel));
instanceInfo.setLastUpdatedTimestamp();
vip = instanceInfo.getVIPAddress();
svip = instanceInfo.getSecureVipAddress();
}
this.invalidateCache(appName, vip, svip);
} finally {
this.read.unlock();
}
Object var16 = this.lock;
synchronized(this.lock) {
if (this.expectedNumberOfClientsSendingRenews > 0) {
--this.expectedNumberOfClientsSendingRenews;
this.updateRenewsPerMinThreshold();
}
return true;
}
}