1.Eureka服务端 有三层缓存
第一层readOnlyCacheMap 使用ConcurrentHashMap做的map,可以通过配置开关控制,默认是打开的
第二层readWriteCacheMap 使用的是google的loadingcache
第三层registry,是个ConcurrentHashMap存储的存储appName和ConcurrentHashMap做value,里层的是用实例id和实例
第一层和第二次在ResponseCacheImpl类中
第三层在AbstractInstanceRegistry中
2.如果开启readCacheMap的化,会启动一个定时器,每responseCacheUpdateIntervalMs(默认30)秒从readWriteCacheMap中更新一次数据 遍历readCacheMap的keySet,取出readWriteCacheMap的value和readOnlyCacheMap中的value比较,如果不相等用前者覆盖后者
ResponseCacheImpl(EurekaServerConfig serverConfig, ServerCodecs serverCodecs, AbstractInstanceRegistry registry) {
。。。
if (shouldUseReadOnlyResponseCache) {
timer.schedule(getCacheUpdateTask(),
new Date(((System.currentTimeMillis() / responseCacheUpdateIntervalMs) * responseCacheUpdateIntervalMs)
+ responseCacheUpdateIntervalMs),
responseCacheUpdateIntervalMs);
}
。。。
}
private TimerTask getCacheUpdateTask() {
return new TimerTask() {
@Override
public void run() {
logger.debug("Updating the client cache from response cache");
for (Key key : readOnlyCacheMap.keySet()) {
if (logger.isDebugEnabled()) {
Object[] args = {key.getEntityType(), key.getName(), key.getVersion(), key.getType()};
logger.debug("Updating the client cache from response cache for key : {} {} {} {}", args);
}
try {
CurrentRequestVersion.set(key.getVersion());
Value cacheValue = readWriteCacheMap.get(key);
Value currentCacheValue = readOnlyCacheMap.get(key);
if (cacheValue != currentCacheValue) {
readOnlyCacheMap.put(key, cacheValue);
}
} catch (Throwable th) {
logger.error("Error while updating the client cache from response cache", th);
}
}
}
};
}
3.获取数据是如果开启readCacheMap,先从readCacheMap获取,如果为空再去readWirteCache获取再写到readOnlyCache
Value getValue(final Key key, boolean useReadOnlyCache) {
Value payload = null;
try {
if (useReadOnlyCache) {
final Value currentPayload = readOnlyCacheMap.get(key);
if (currentPayload != null) {
payload = currentPayload;
} else {
payload = readWriteCacheMap.get(key);
readOnlyCacheMap.put(key, payload);
}
} else {
payload = readWriteCacheMap.get(key);
}
} catch (Throwable t) {
logger.error("Cannot get value for key :" + key, t);
}
return payload;
}
4.服务注册时,会把数据写道registry和readWriteCacheMap中
public void register(InstanceInfo registrant, int leaseDuration, boolean isReplication) {
try {
read.lock();
。。。。
invalidateCache(registrant.getAppName(), registrant.getVIPAddress(), registrant.getSecureVipAddress());
logger.info("Registered instance {}/{} with status {} (replication={})",
registrant.getAppName(), registrant.getId(), registrant.getStatus(), isReplication);
} finally {
read.unlock();
}
}
private void invalidateCache(String appName, @Nullable String vipAddress, @Nullable String secureVipAddress) {
// invalidate cache
responseCache.invalidate(appName, vipAddress, secureVipAddress);
}