EnableEurekaServer注解导入了EurekaServerMarkerConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class)
public @interface EnableEurekaServer {
}
EurekaServerMarkerConfiguration仅仅创建了一个Marker的Bean
@Configuration(proxyBeanMethods = false)
public class EurekaServerMarkerConfiguration {
@Bean
public Marker eurekaServerMarkerBean() {
return new Marker();
}
class Marker {
}
}
spring-cloud-netflix-eureka-server/2.2.9.RELEASE/spring-cloud-netflix-eureka-server-2.2.9.RELEASE.jar!/META-INF/spring.factories
自动装配EurekaServerAutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration
EurekaServerAutoConfiguration
@Configuration(proxyBeanMethods = false)
//导入了EurekaServerInitializerConfiguration
@Import(EurekaServerInitializerConfiguration.class)
//需要存在Marker的Bean
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
//省略,注入了各类Bean
}
EurekaServerInitializerConfiguration实现了SmartLifecycle接口
@Configuration(proxyBeanMethods = false)
public class EurekaServerInitializerConfiguration
implements ServletContextAware, SmartLifecycle, Ordered {
@Override
public void start() {
new Thread(() -> {
try {
//看这里
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();
}
}
EurekaServerBootstrap
public void contextInitialized(ServletContext context) {
try {
//初始化Eureka环境变量的取值途径
initEurekaEnvironment();
//看这里,初始化Eureka上下文
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);
}
}
protected void initEurekaServerContext() throws Exception {
//省略部分代码
EurekaServerContextHolder.initialize(this.serverContext);
log.info("Initialized server context");
int registryCount = this.registry.syncUp();
//看这里
this.registry.openForTraffic(this.applicationInfoManager, registryCount);
// Register all monitoring statistics.
EurekaMonitors.registerAllStats();
}
InstanceRegistry
@Override
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {
//如果count为0,则修改为defaultOpenForTrafficCount默认为1
super.openForTraffic(applicationInfoManager,
count == 0 ? this.defaultOpenForTrafficCount : count);
}
PeerAwareInstanceRegistryImpl
@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.expectedNumberOfClientsSendingRenews = count;
//计算期望每分钟收到的客户端心跳续约次数的阈值 numberOfRenewsPerMinThreshold
updateRenewsPerMinThreshold();
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();
}
@Override
public boolean isLeaseExpirationEnabled() {
//enableSelfPreservation默认为true,开启自我保护机制
if (!isSelfPreservationModeEnabled()) {
return true;
}
//如果每分钟期望收到的心跳次数大于0 且 上一分钟的收到的客户端的心跳次数大于每分钟期望收到的心跳次数,则返回true
//当上一分钟的收到的客户端的心跳次数小于等于每分钟期望收到的心跳次数
//则代表上一分钟有超发15%的客户端没有及时发送心跳
//此时开启自我保护机制,返回false。
return numberOfRenewsPerMinThreshold > 0 && getNumOfRenewsInLastMin() > numberOfRenewsPerMinThreshold;
}
@Override
public void register(final InstanceInfo info, final boolean isReplication) {
//默认服务实例过期时间90s
int leaseDuration = Lease.DEFAULT_DURATION_IN_SECS;
//使用客户端传递过来的过期时间
if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) {
leaseDuration = info.getLeaseInfo().getDurationInSecs();
}
//实例注册
super.register(info, leaseDuration, isReplication);
//将实例信息同步给其他eurek节点
replicateToPeers(Action.Register, info.getAppName(), info.getId(), info, null, isReplication);
}
@Override
public void init(PeerEurekaNodes peerEurekaNodes) throws Exception {
//启动MeasuredRate定时任务
this.numberOfReplicationsLastMin.start();
this.peerEurekaNodes = peerEurekaNodes;
//初始化服务实例缓存
initializedResponseCache();
scheduleRenewalThresholdUpdateTask();
initRemoteRegionRegistry();
try {
Monitors.registerObject(this);
} catch (Throwable e) {
logger.warn("Cannot register the JMX monitor for the InstanceRegistry :", e);
}
}
private void replicateToPeers(Action action, String appName, String id,
InstanceInfo info /* optional */,
InstanceStatus newStatus /* optional */, boolean isReplication) {
Stopwatch tracer = action.getTimer().start();
try {
if (isReplication) {
numberOfReplicationsLastMin.increment();
}
// If it is a replication already, do not replicate again as this will create a poison replication
if (peerEurekaNodes == Collections.EMPTY_LIST || isReplication) {
return;
}
//循环所有其他的eureka节点
for (final PeerEurekaNode node : peerEurekaNodes.getPeerEurekaNodes()) {
//跳过自己
if (peerEurekaNodes.isThisMyUrl(node.getServiceUrl())) {
continue;
}
//同步给其他eureka节点
replicateInstanceActionsToPeers(action, appName, id, info, newStatus, node);
}
} finally {
tracer.stop();
}
}
private void replicateInstanceActionsToPeers(Action action, String appName,
String id, InstanceInfo info, InstanceStatus newStatus,
PeerEurekaNode node) {
try {
InstanceInfo infoFromRegistry;
CurrentRequestVersion.set(Version.V2);
//根据不同的action,通过jersey发送不同的请求给其他的eureka节点
switch (action) {
case Cancel:
node.cancel(appName, id);
break;
case Heartbeat:
InstanceStatus overriddenStatus = overriddenInstanceStatusMap.get(id);
infoFromRegistry = getInstanceByAppAndId(appName, id, false);
node.heartbeat(appName, id, infoFromRegistry, overriddenStatus, false);
break;
case Register:
node.register(info);
break;
case StatusUpdate:
infoFromRegistry = getInstanceByAppAndId(appName, id, false);
node.statusUpdate(appName, id, newStatus, infoFromRegistry);
break;
case DeleteStatusOverride:
infoFromRegistry = getInstanceByAppAndId(appName, id, false);
node.deleteStatusOverride(appName, id, infoFromRegistry);
break;
}
} catch (Throwable t) {
logger.error("Cannot replicate information to {} for action {}", node.getServiceUrl(), action.name(), t);
} finally {
CurrentRequestVersion.remove();
}
}
AbstractInstanceRegistry
protected void updateRenewsPerMinThreshold() {
//expectedNumberOfClientsSendingRenews客户端实例数量,每当客户端实例注册到服务端时,该值加一
//getExpectedClientRenewalIntervalSeconds默认为30秒,客户端发送心跳的间隔时间
//getRenewalPercentThreshold默认为0.85,允许小于%15的客户端没有及时发送心跳时不触发服务端自我保护
this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfClientsSendingRenews
* (60.0 / serverConfig.getExpectedClientRenewalIntervalSeconds())
* serverConfig.getRenewalPercentThreshold());
}
protected void postInit() {
//启动MeasuredRate定时任务
renewsLastMin.start();
if (evictionTaskRef.get() != null) {
evictionTaskRef.get().cancel();
}
evictionTaskRef.set(new EvictionTask());
//启动服务剔除的定时任务
//getEvictionIntervalTimerInMs默认60s
evictionTimer.schedule(evictionTaskRef.get(),
serverConfig.getEvictionIntervalTimerInMs(),
serverConfig.getEvictionIntervalTimerInMs());
}
class EvictionTask extends TimerTask {
//记录上一次任务开始执行的时间
private final AtomicLong lastExecutionNanosRef = new AtomicLong(0l);
@Override
public void run() {
try {
//获取补偿时间
long compensationTimeMs = getCompensationTimeMs();
logger.info("Running the evict task with compensationTime {}ms", compensationTimeMs);
evict(compensationTimeMs);
} catch (Throwable e) {
logger.error("Could not run the evict task", e);
}
}
long getCompensationTimeMs() {
//获取当前时间(本次任务的开始时间)
long currNanos = getCurrentTimeNano();
//获取上一次定时任务的开始时间
//将当前时间赋值给lastExecutionNanosRef
long lastNanos = lastExecutionNanosRef.getAndSet(currNanos);
if (lastNanos == 0l) {
return 0l;
}
//计算两次任务执行时间的差值
long elapsedMs = TimeUnit.NANOSECONDS.toMillis(currNanos - lastNanos);
//两次任务的执行时间如果差值大于EvictionIntervalTimerInMs,则说明任务没有及时执行
//compensationTime为任务延迟的时间
long compensationTime = elapsedMs - serverConfig.getEvictionIntervalTimerInMs();
//如果compensationTime大于0则返回compensationTime,否则返回0
return compensationTime <= 0l ? 0l : compensationTime;
}
}
public void evict(long additionalLeaseMs) {
logger.debug("Running the evict task");
//如果开启了自我保护机制(isLeaseExpirationEnabled返回false),则不剔除服务,直接返回
if (!isLeaseExpirationEnabled()) {
logger.debug("DS: lease expiration is currently disabled.");
return;
}
List<Lease<InstanceInfo>> expiredLeases = new ArrayList<>();
//遍历所有的服务
for (Entry<String, Map<String, Lease<InstanceInfo>>> groupEntry : registry.entrySet()) {
Map<String, Lease<InstanceInfo>> leaseMap = groupEntry.getValue();
if (leaseMap != null) {
//遍历服务下的实例
for (Entry<String, Lease<InstanceInfo>> leaseEntry : leaseMap.entrySet()) {
Lease<InstanceInfo> lease = leaseEntry.getValue();
//如果过期,加入到expiredLeases中
if (lease.isExpired(additionalLeaseMs) && lease.getHolder() != null) {
expiredLeases.add(lease);
}
}
}
}
//获取所有服务的所有实例个数
int registrySize = (int) getLocalRegistrySize();
//实例个数的85%
int registrySizeThreshold = (int) (registrySize * serverConfig.getRenewalPercentThreshold());
//差值为15%的实例个数
int evictionLimit = registrySize - registrySizeThreshold;
//如果expiredLeases的数量大于evictionLimit ,则取evictionLimit (最多剔除15%的过期实例)
int toEvict = Math.min(expiredLeases.size(), evictionLimit);
if (toEvict > 0) {
logger.info("Evicting {} items (expired={}, evictionLimit={})", toEvict, expiredLeases.size(), evictionLimit);
Random random = new Random(System.currentTimeMillis());
for (int i = 0; i < toEvict; i++) {
// Pick a random item (Knuth shuffle algorithm) 公平洗牌
//随机从expiredLeases中剔除过期实例
int next = i + random.nextInt(expiredLeases.size() - i);
Collections.swap(expiredLeases, i, next);
Lease<InstanceInfo> lease = expiredLeases.get(i);
String appName = lease.getHolder().getAppName();
String id = lease.getHolder().getId();
EXPIRED.increment();
logger.warn("DS: Registry: expired lease for {}/{}", appName, id);
//剔除过期实例
internalCancel(appName, id, false);
}
}
}
public long getNumOfRenewsInLastMin() {
//获取上一分钟收到的客户端心跳次数
return renewsLastMin.getCount();
}
protected boolean internalCancel(String appName, String id, boolean isReplication) {
read.lock();
try {
CANCEL.increment(isReplication);
//获取服务对应的实例列表
Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
Lease<InstanceInfo> leaseToCancel = null;
if (gMap != null) {
//获取实例
leaseToCancel = gMap.remove(id);
}
recentCanceledQueue.add(new Pair<Long, String>(System.currentTimeMillis(), appName + "(" + id + ")"));
InstanceStatus instanceStatus = overriddenInstanceStatusMap.remove(id);
if (instanceStatus != null) {
logger.debug("Removed instance id {} from the overridden map which has value {}", id, instanceStatus.name());
}
if (leaseToCancel == null) {
CANCEL_NOT_FOUND.increment(isReplication);
logger.warn("DS: Registry: cancel failed because Lease is not registered for: {}/{}", appName, id);
return false;
} else {
//设置evictionTimestamp(实例过期时间)为当前时间
leaseToCancel.cancel();
InstanceInfo instanceInfo = leaseToCancel.getHolder();
String vip = null;
String svip = null;
if (instanceInfo != null) {
//修改为实例的actionType为DELETED
instanceInfo.setActionType(ActionType.DELETED);
//被修改过的实例加入到recentlyChangedQueue (客户端增量同步eureka服务端的实例列表时,从recentlyChangedQueue取值)
recentlyChangedQueue.add(new RecentlyChangedItem(leaseToCancel));
//更新实例的LastUpdatedTimestamp
instanceInfo.setLastUpdatedTimestamp();
vip = instanceInfo.getVIPAddress();
svip = instanceInfo.getSecureVipAddress();
}
//将服务端的readWriteCacheMap对应的服务列表缓存置空
invalidateCache(appName, vip, svip);
logger.info("Cancelled instance {}/{} (replication={})", appName, id, isReplication);
}
} finally {
read.unlock();
}
synchronized (lock) {
if (this.expectedNumberOfClientsSendingRenews > 0) {
//实例剔除了,则expectedNumberOfClientsSendingRenews 减一
this.expectedNumberOfClientsSendingRenews = this.expectedNumberOfClientsSendingRenews - 1;
//重新计算 期望每分钟收到的客户端心跳续约次数的阈值
updateRenewsPerMinThreshold();
}
}
return true;
}
@Override
public synchronized void initializedResponseCache() {
if (responseCache == null) {
responseCache = new ResponseCacheImpl(serverConfig, serverCodecs, this);
}
}
public Applications getApplications() {
//默认为false
boolean disableTransparentFallback = serverConfig.disableTransparentFallbackToOtherRegion();
if (disableTransparentFallback) {
return getApplicationsFromLocalRegionOnly();
} else {
return getApplicationsFromAllRemoteRegions(); // Behavior of falling back to remote region can be disabled.
}
}
public Applications getApplicationsFromMultipleRegions(String[] remoteRegions) {
//省略部分代码
//所有服务应用
Applications apps = new Applications();
apps.setVersion(1L);
//循环所有的服务
for (Entry<String, Map<String, Lease<InstanceInfo>>> entry : registry.entrySet()) {
//一个服务对应一个Application
Application app = null;
if (entry.getValue() != null) {
//循环服务下所有的实例
for (Entry<String, Lease<InstanceInfo>> stringLeaseEntry : entry.getValue().entrySet()) {
Lease<InstanceInfo> lease = stringLeaseEntry.getValue();
if (app == null) {
app = new Application(lease.getHolder().getAppName());
}
//添加实例到app
app.addInstance(decorateInstanceInfo(lease));
}
}
if (app != null) {
//添加app到apps
apps.addApplication(app);
}
}
//省略部分代码
apps.setAppsHashCode(apps.getReconcileHashCode());
return apps;
}
public Applications getApplicationDeltas() {
GET_ALL_CACHE_MISS_DELTA.increment();
Applications apps = new Applications();
apps.setVersion(responseCache.getVersionDelta().get());
Map<String, Application> applicationInstancesMap = new HashMap<String, Application>();
write.lock();
try {
//迭代recentlyChangedQueue
Iterator<RecentlyChangedItem> iter = this.recentlyChangedQueue.iterator();
logger.debug("The number of elements in the delta queue is : {}",
this.recentlyChangedQueue.size());
while (iter.hasNext()) {
Lease<InstanceInfo> lease = iter.next().getLeaseInfo();
InstanceInfo instanceInfo = lease.getHolder();
logger.debug(
"The instance id {} is found with status {} and actiontype {}",
instanceInfo.getId(), instanceInfo.getStatus().name(), instanceInfo.getActionType().name());
//从applicationInstancesMap获取服务
Application app = applicationInstancesMap.get(instanceInfo
.getAppName());
//不存在
if (app == null) {
//新建一个Application
app = new Application(instanceInfo.getAppName());
//建立服务名称和服务的映射关系
applicationInstancesMap.put(instanceInfo.getAppName(), app);
//向apps添加app
apps.addApplication(app);
}
//存在,则添加实例到app中
app.addInstance(new InstanceInfo(decorateInstanceInfo(lease)));
}
//省略部分代码
//获取所有的服务应用
Applications allApps = getApplications(!disableTransparentFallback);
//设置所有服务应用的hashCode,客户端增量同步时服务信息时,还需要对比hashCode,当出现不一致时,则要发起一次全量同步的请求
apps.setAppsHashCode(allApps.getReconcileHashCode());
return apps;
} finally {
write.unlock();
}
}
MeasuredRate
//记录上一分钟收到的客户端心跳的次数
private final AtomicLong lastBucket = new AtomicLong(0);
//记录当前收到的客户端心跳的次数
private final AtomicLong currentBucket = new AtomicLong(0);
public synchronized void start() {
if (!isActive) {
//sampleInterval写死为60s
timer.schedule(new TimerTask() {
@Override
public void run() {
try {
//获取currentBucket的值设置到lastBucket
//将currentBucket设置为0
lastBucket.set(currentBucket.getAndSet(0));
} catch (Throwable e) {
logger.error("Cannot reset the Measured Rate", e);
}
}
}, sampleInterval, sampleInterval);
isActive = true;
}
}
public long getCount() {
return lastBucket.get();
}
public void increment() {
currentBucket.incrementAndGet();
}
Lease
//客户端心跳续约时更新lastUpdateTimestamp,该时间为 当前时间 加上 过期时间(默认为90s)
public void renew() {
lastUpdateTimestamp = System.currentTimeMillis() + duration;
}
/**
* Checks if the lease of a given {@link com.netflix.appinfo.InstanceInfo} has expired or not.
*
* Note that due to renew() doing the 'wrong" thing and setting lastUpdateTimestamp to +duration more than
* what it should be, the expiry will actually be 2 * duration. This is a minor bug and should only affect
* instances that ungracefully shutdown. Due to possible wide ranging impact to existing usage, this will
* not be fixed.
*
* @param additionalLeaseMs any additional lease time to add to the lease evaluation in ms.
*/
public boolean isExpired(long additionalLeaseMs) {
//如果过期时间>0(已经被下线了) 或者 (当前时间 大于 (lastUpdateTimestamp+过期时间+补偿时间 显然服务端判断客户端过期的时间变成了两倍,加了两次duration) )
//可以看到上面的官方注释,就是两倍,并且不会修复该问题。
return (evictionTimestamp > 0 || System.currentTimeMillis() > (lastUpdateTimestamp + duration + additionalLeaseMs));
}
DefaultEurekaServerContext
@PostConstruct
@Override
public void initialize() {
logger.info("Initializing ...");
//看这里
peerEurekaNodes.start();
try {
//初始化registry
registry.init(peerEurekaNodes);
} catch (Exception e) {
throw new RuntimeException(e);
}
logger.info("Initialized");
}
PeerEurekaNodes
public void start() {
taskExecutor = Executors.newSingleThreadScheduledExecutor(
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "Eureka-PeerNodesUpdater");
thread.setDaemon(true);
return thread;
}
}
);
try {
updatePeerEurekaNodes(resolvePeerUrls());
Runnable peersUpdateTask = new Runnable() {
@Override
public void run() {
try {
updatePeerEurekaNodes(resolvePeerUrls());
} catch (Throwable e) {
logger.error("Cannot update the replica Nodes", e);
}
}
};
//定时更新其他eureka节点信息
taskExecutor.scheduleWithFixedDelay(
peersUpdateTask,
serverConfig.getPeerEurekaNodesUpdateIntervalMs(),
//默认为10分钟
serverConfig.getPeerEurekaNodesUpdateIntervalMs(),
TimeUnit.MILLISECONDS
);
} catch (Exception e) {
throw new IllegalStateException(e);
}
for (PeerEurekaNode node : peerEurekaNodes) {
logger.info("Replica node URL: {}", node.getServiceUrl());
}
}
//获取其他eureka节点url。
protected List<String> resolvePeerUrls() {
InstanceInfo myInfo = applicationInfoManager.getInfo();
//默认获取的为defaultZone
String zone = InstanceInfo.getZone(clientConfig.getAvailabilityZones(clientConfig.getRegion()), myInfo);
//从clientConfig中获取到defaultZone对应的值
List<String> replicaUrls = EndpointUtils
.getDiscoveryServiceUrls(clientConfig, zone, new EndpointUtils.InstanceInfoBasedUrlRandomizer(myInfo));
int idx = 0;
while (idx < replicaUrls.size()) {
//移除掉自己。
if (isThisMyUrl(replicaUrls.get(idx))) {
replicaUrls.remove(idx);
} else {
idx++;
}
}
return replicaUrls;
}
protected void updatePeerEurekaNodes(List<String> newPeerUrls) {
if (newPeerUrls.isEmpty()) {
logger.warn("The replica size seems to be empty. Check the route 53 DNS Registry");
return;
}
//之前的eureka节点url
Set<String> toShutdown = new HashSet<>(peerEurekaNodeUrls);
//移除其中的newPeerUrls
toShutdown.removeAll(newPeerUrls);
//现在的eureka节点url
Set<String> toAdd = new HashSet<>(newPeerUrls);
//移除其中的peerEurekaNodeUrls
toAdd.removeAll(peerEurekaNodeUrls);
//两个集合都会为空,说明没有发生变化。直接返回
if (toShutdown.isEmpty() && toAdd.isEmpty()) { // No change
return;
}
// Remove peers no long available
//之前的eureka节点
List<PeerEurekaNode> newNodeList = new ArrayList<>(peerEurekaNodes);
if (!toShutdown.isEmpty()) {
logger.info("Removing no longer available peer nodes {}", toShutdown);
int i = 0;
while (i < newNodeList.size()) {
PeerEurekaNode eurekaNode = newNodeList.get(i);
if (toShutdown.contains(eurekaNode.getServiceUrl())) {
//从之前的eureka节点移除掉不再需要的eureka节点
newNodeList.remove(i);
//调用shutDown方法
eurekaNode.shutDown();
} else {
i++;
}
}
}
// Add new peers
//本次新增的eureka节点url
if (!toAdd.isEmpty()) {
logger.info("Adding new peer nodes {}", toAdd);
for (String peerUrl : toAdd) {
//创建新的eureka节点
newNodeList.add(createPeerEurekaNode(peerUrl));
}
}
//peerEurekaNodes 设置为 新的eureka节点
this.peerEurekaNodes = newNodeList;
//peerEurekaNodeUrls 设置为 新的eureka节点url
this.peerEurekaNodeUrls = new HashSet<>(newPeerUrls);
}
ResponseCacheImpl
ResponseCacheImpl(EurekaServerConfig serverConfig, ServerCodecs serverCodecs, AbstractInstanceRegistry registry) {
this.serverConfig = serverConfig;
this.serverCodecs = serverCodecs;
//默认为true
this.shouldUseReadOnlyResponseCache = serverConfig.shouldUseReadOnlyResponseCache();
this.registry = registry;
long responseCacheUpdateIntervalMs = serverConfig.getResponseCacheUpdateIntervalMs();
//初始化readWriteCacheMap(缓存服务实例)
this.readWriteCacheMap =
CacheBuilder.newBuilder().initialCapacity(serverConfig.getInitialCapacityOfResponseCache())
.expireAfterWrite(serverConfig.getResponseCacheAutoExpirationInSeconds(), TimeUnit.SECONDS)
.removalListener(new RemovalListener<Key, Value>() {
@Override
public void onRemoval(RemovalNotification<Key, Value> notification) {
Key removedKey = notification.getKey();
if (removedKey.hasRegions()) {
Key cloneWithNoRegions = removedKey.cloneWithoutRegions();
regionSpecificKeys.remove(cloneWithNoRegions, removedKey);
}
}
})
.build(new CacheLoader<Key, Value>() {
@Override
public Value load(Key key) throws Exception {
if (key.hasRegions()) {
Key cloneWithNoRegions = key.cloneWithoutRegions();
regionSpecificKeys.put(cloneWithNoRegions, key);
}
//解析key,获取到对应的value。
Value value = generatePayload(key);
return value;
}
});
//定时更新缓存数据
if (shouldUseReadOnlyResponseCache) {
timer.schedule(getCacheUpdateTask(),
new Date(((System.currentTimeMillis() / responseCacheUpdateIntervalMs) * responseCacheUpdateIntervalMs)
+ responseCacheUpdateIntervalMs),
responseCacheUpdateIntervalMs);
}
try {
Monitors.registerObject(this);
} catch (Throwable e) {
logger.warn("Cannot register the JMX monitor for the InstanceRegistry", e);
}
}
private TimerTask getCacheUpdateTask() {
return new TimerTask() {
@Override
public void run() {
logger.debug("Updating the client cache from response cache");
//遍历readOnlyCacheMap(缓存服务实例)
for (Key key : readOnlyCacheMap.keySet()) {
if (logger.isDebugEnabled()) {
logger.debug("Updating the client cache from response cache for key : {} {} {} {}",
key.getEntityType(), key.getName(), key.getVersion(), key.getType());
}
try {
CurrentRequestVersion.set(key.getVersion());
//比对readWriteCacheMap和readOnlyCacheMap相同key的value
Value cacheValue = readWriteCacheMap.get(key);
Value currentCacheValue = readOnlyCacheMap.get(key);
if (cacheValue != currentCacheValue) {
//不相等,则使用readWriteCacheMap的value覆盖掉readOnlyCacheMap的
readOnlyCacheMap.put(key, cacheValue);
}
} catch (Throwable th) {
logger.error("Error while updating the client cache from response cache for key {}", key.toStringCompact(), th);
} finally {
CurrentRequestVersion.remove();
}
}
}
};
}
Value getValue(final Key key, boolean useReadOnlyCache) {
Value payload = null;
try {
//useReadOnlyCache就是shouldUseReadOnlyResponseCache。
if (useReadOnlyCache) {
//先从readOnlyCacheMap获取数据
final Value currentPayload = readOnlyCacheMap.get(key);
if (currentPayload != null) {
payload = currentPayload;
}
else {
//readOnlyCacheMap没有该数据,则从readWriteCacheMap获取
payload = readWriteCacheMap.get(key);
//在放入readOnlyCacheMap中
readOnlyCacheMap.put(key, payload);
}
} else {
payload = readWriteCacheMap.get(key);
}
} catch (Throwable t) {
logger.error("Cannot get value for key : {}", key, t);
}
return payload;
}
private Value generatePayload(Key key) {
Stopwatch tracer = null;
try {
String payload;
switch (key.getEntityType()) {
case Application:
boolean isRemoteRegionRequested = key.hasRegions();
//全量获取服务实例
if (ALL_APPS.equals(key.getName())) {
if (isRemoteRegionRequested) {
tracer = serializeAllAppsWithRemoteRegionTimer.start();
payload = getPayLoad(key, registry.getApplicationsFromMultipleRegions(key.getRegions()));
} else {
tracer = serializeAllAppsTimer.start();
//registry.getApplications() 从registry获取所有的服务实例
payload = getPayLoad(key, registry.getApplications());
}
}
//增量获取服务实例
else if (ALL_APPS_DELTA.equals(key.getName())) {
if (isRemoteRegionRequested) {
tracer = serializeDeltaAppsWithRemoteRegionTimer.start();
versionDeltaWithRegions.incrementAndGet();
versionDeltaWithRegionsLegacy.incrementAndGet();
payload = getPayLoad(key,
registry.getApplicationDeltasFromMultipleRegions(key.getRegions()));
} else {
tracer = serializeDeltaAppsTimer.start();
versionDelta.incrementAndGet();
versionDeltaLegacy.incrementAndGet();
//registry.getApplicationDeltas() 从recentlyChangedQueue获取服务实例
payload = getPayLoad(key, registry.getApplicationDeltas());
}
}
else {
tracer = serializeOneApptimer.start();
//通过key获取value,获取某个指定的服务列表
payload = getPayLoad(key, registry.getApplication(key.getName()));
}
break;
case VIP:
case SVIP:
tracer = serializeViptimer.start();
payload = getPayLoad(key, getApplicationsForVip(key, registry));
break;
default:
logger.error("Unidentified entity type: {} found in the cache key.", key.getEntityType());
payload = "";
break;
}
return new Value(payload);
} finally {
if (tracer != null) {
tracer.stop();
}
}
}