当客户端请求全量更新的时候,会调用ApplicationsResource#getContainers这个方法。如果是增量,会调用ApplicationsResource#getContainerDifferential这个方法。他主要是获取只读缓存的内容,如果只读缓存不存在,返回只读读写缓存的内容。
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方法
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(),直接从注册表数据拿值。
所以在服务发现的时候,都是走缓存,提高效率,但是为了保证数据的一致性,还会定期更新、清空缓存。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。