Eureka - 服務發現(Server)

當客戶端請求全量更新的時候,會調用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;
}

上面的代碼流程以下:
image.png
readOnlyCacheMap的值是怎麼來的呢?
Eureka - Server服務啓動PeerAwareInstanceRegistry#init方法中提到了ResponseCacheImpl構造函數中,沒30秒會把readWriteCacheMap的值賦值給readOnlyCacheMap。
image.png
ResponseCacheImpl初始化的時候,咱們看到他默認180秒後會過時。緩存

this.readWriteCacheMap =
    CacheBuilder.newBuilder().initialCapacity(serverConfig.getInitialCapacityOfResponseCache())
            .expireAfterWrite(serverConfig.getResponseCacheAutoExpirationInSeconds(), TimeUnit.SECONDS)
            // 其餘略;

Eureka - Server服務啓動中提到,PeerAwareInstanceRegistryImpl#syncUp()每次註冊都會主動清空readWriteCacheMap的值。
image.png
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(),直接從註冊表數據拿值。
image.png
因此在服務發現的時候,都是走緩存,提升效率,可是爲了保證數據的一致性,還會按期更新、清空緩存。函數

相關文章
相關標籤/搜索