【Eureka】【07】Eureka Server緩存

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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章