(转)springCloud Eureka的缓存机制

转自:https://www.jianshu.com/p/ae4f0c8b8135

第一层缓存:readOnlyCacheMap,本质上是ConcurrentHashMap

第二层缓存:readWriteCacheMap,本质上是Guava缓存

缓存用途

Eureka Client获取注册列表时,首先判断是否开启了二级缓存,如果开启了则从readOnlyCacheMap中获取,否则从readWriteCacheMap中获取。

 

Eureka Server的缓存机制依赖于谷歌的gauva cache , 在Eureka中通过

com.netflix.eureka.registry.ResponseCacheImpl , 这个操作类来实现缓存的机制。

ResponseCacheImpl(EurekaServerConfig serverConfig, ServerCodecs serverCodecs, AbstractInstanceRegistry registry) {
    this.serverConfig = serverConfig;
    this.serverCodecs = serverCodecs;
    // 是否使用只读缓存
    this.shouldUseReadOnlyResponseCache = serverConfig.shouldUseReadOnlyResponseCache();
    this.registry = registry;
    // 缓存更新的时间间隔(用定时器更新,定时器的时间默认30秒执行一次)
    long responseCacheUpdateIntervalMs = serverConfig.getResponseCacheUpdateIntervalMs();
    // 构建读写缓存
    this.readWriteCacheMap =
            CacheBuilder.newBuilder().initialCapacity(1000)
                    .expireAfterWrite(serverConfig.getResponseCacheAutoExpirationInSeconds(), TimeUnit.SECONDS)
                    .removalListener(new RemovalListener<Key, Value>() {
                        @Override
                        public void onRemoval(RemovalNotification<Key, Value> notification) {
                            Key removedKey = notification.getKey();
                            if (removedKey.hasRegions()) {
                                Key cloneWithNoRegions = removedKey.cloneWithoutRegions();
                                regionSpecificKeys.remove(cloneWithNoRegions, removedKey);
                            }
                        }
                    })
                    // 缓存加载器,当缓存不存在时,会自动执行load方法,进行缓存加载。同时返回缓存数据
                    .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 的数据至readOnlyCacheMap
    if (shouldUseReadOnlyResponseCache) {
        timer.schedule(getCacheUpdateTask(),
                new Date(((System.currentTimeMillis() / responseCacheUpdateIntervalMs) * responseCacheUpdateIntervalMs)
                        + responseCacheUpdateIntervalMs),
                responseCacheUpdateIntervalMs);
    }

    try {
        Monitors.registerObject(this);
    } catch (Throwable e) {
        logger.warn("Cannot register the JMX monitor for the InstanceRegistry", e);
    }
}

通过上面可以很简单的看出, Eureka Server的缓存是通过一个只读,一个读写缓存来实现的。

readWriteCacheMap : 此处存放的是最终的缓存, 当服务下线,过期,注册,状态变更,都会来清除这个缓存里面的数据。 然后通过CacheLoader进行缓存加载,在进行readWriteCacheMap.get(key)的时候,首先看这个缓存里面有没有该数据,如果没有则通过CacheLoader的load方法去加载,加载成功之后将数据放入缓存,同时返回数据

readOnlyCacheMap : 这是一个JVM的CurrentHashMap只读缓存,这个主要是为了供客户端获取注册信息时使用,其缓存更新,依赖于定时器的更新,通过和readWriteCacheMap 的值做对比,如果数据不一致,则以readWriteCacheMap 的数据为准。

responseCacheUpdateIntervalMs : readOnlyCacheMap 缓存更新的定时器时间间隔,默认为30秒

responseCacheAutoExpirationInSeconds : readWriteCacheMap 缓存过期时间,默认为 180 秒 。

CacheUpdateTask

readOnlyCacheMap 定时器的任务执行类。

private TimerTask getCacheUpdateTask() {
    return new TimerTask() {
        @Override
        public void run() {
            logger.debug("Updating the client cache from response cache");
            // 循环readOnlyCacheMap里面的KEY
            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());
                    // 从readWriteCacheMap获取数据
                    Value cacheValue = readWriteCacheMap.get(key);
                    // 当前的只读数据
                    Value currentCacheValue = readOnlyCacheMap.get(key);
                    // 判断数据是否一致
                    if (cacheValue != currentCacheValue) {
                        // 如果不一致,覆盖只读缓存里面的数据,以readWriteCacheMap为准
                        readOnlyCacheMap.put(key, cacheValue);
                    }
                } catch (Throwable th) {
                    logger.error("Error while updating the client cache from response cache", th);
                }
            }
        }
    };
}

Eureka Client缓存机制

Eureka Client缓存机制很简单,设置了一个每30秒执行一次的定时任务,定时去服务端获取注册信息。获取之后,存入本地内存。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值