當客戶端請求全量更新的時候,會調用ApplicationsResource#getContainers這個方法。若是是增量,會調用ApplicationsResource#getContainerDifferential這個方法。他主要是獲取只讀緩存的內容,若是隻讀緩存不存在,返回只讀讀寫緩存的內容。segmentfault
public Response getContainers(@PathParam("version") String version, @HeaderParam(HEADER_ACCEPT) String acceptHeader, @HeaderParam(HEADER_ACCEPT_ENCODING) String acceptEncoding, @HeaderParam(EurekaAccept.HTTP_X_EUREKA_ACCEPT) String eurekaAccept, @Context UriInfo uriInfo, @Nullable @QueryParam("regions") String regionsStr) { //其餘略 response = Response.ok(responseCache.get(cacheKey)) .build(); //其餘略 CurrentRequestVersion.remove(); return response; } public String get(final Key key) { return get(key, shouldUseReadOnlyResponseCache); } @VisibleForTesting String get(final Key key, boolean useReadOnlyCache) { Value payload = getValue(key, useReadOnlyCache); if (payload == null || payload.getPayload().equals(EMPTY_PAYLOAD)) { return null; } else { return payload.getPayload(); } } @VisibleForTesting 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; }
上面的代碼流程以下:
readOnlyCacheMap的值是怎麼來的呢?
Eureka - Server服務啓動PeerAwareInstanceRegistry#init方法中提到了ResponseCacheImpl構造函數中,沒30秒會把readWriteCacheMap的值賦值給readOnlyCacheMap。
ResponseCacheImpl初始化的時候,咱們看到他默認180秒後會過時。緩存
this.readWriteCacheMap = CacheBuilder.newBuilder().initialCapacity(serverConfig.getInitialCapacityOfResponseCache()) .expireAfterWrite(serverConfig.getResponseCacheAutoExpirationInSeconds(), TimeUnit.SECONDS) // 其餘略;
Eureka - Server服務啓動中提到,PeerAwareInstanceRegistryImpl#syncUp()每次註冊都會主動清空readWriteCacheMap的值。
ResponseCacheImpl初始化的時候,還有一個build方法ide
this.readWriteCacheMap = CacheBuilder.newBuilder().initialCapacity(serverConfig.getInitialCapacityOfResponseCache()) // 其餘略 .build(new CacheLoader<Key, Value>() { @Override public Value load(Key key) throws Exception { if (key.hasRegions()) { Key cloneWithNoRegions = key.cloneWithoutRegions(); regionSpecificKeys.put(cloneWithNoRegions, key); } Value value = generatePayload(key); return value; } });
當readWriteCacheMap沒有值的時候,他會調用load方法。若是是全量,就會調用registry.getApplications()這個方法,若是是增量會調用registry.getApplicationDeltas(),直接從註冊表數據拿值。
因此在服務發現的時候,都是走緩存,提升效率,可是爲了保證數據的一致性,還會按期更新、清空緩存。函數