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);
}