(十二)EurekaServer-扩展

1. 读写锁

1.1 位置
// AbstractInstanceRegistry.class
public abstract class AbstractInstanceRegistry implements InstanceRegistry {
    
    // 最近变更队列
    private ConcurrentLinkedQueue<RecentlyChangedItem> recentlyChangedQueue = new ConcurrentLinkedQueue<RecentlyChangedItem>();
    
    private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    // 读锁
    private final Lock read = readWriteLock.readLock();
    // 写锁
    private final Lock write = readWriteLock.writeLock();
    
}
1.2 锁机制
  • 读锁之间不互斥,写锁之间互斥,读写锁之间互斥
  • 当一个线程获取读锁时,另一个线程能获取读锁但是不能获取写锁;当一个线程获取写锁,另一个线程读锁或写锁都不能获取。这个和 InnoDB 的读写锁是一样的
1.3 调用方
  • read:处理客户端注册、下架、状态变更、删除状态
  • write:处理客户端拉取增量注册表
1.4 分析
  • 在上述处理的相关代码中,可以发现共同点就是操作了 recentlyChangedQueue 最近变更队列,读写锁就是服务于这个队列
  • 对于 recentlyChangedQueue 队列,写的场景很多,读的场景只有拉取增量注册表。当多个场景多线程对于 recentlyChangedQueue 进行写操作时,recentlyChangedQueue 的数据结构是线程安全的,所以不用加写锁,但是加读锁和为了配合拉取增量注册表的读场景,保证对 recentlyChangedQueue 写操作时无法读操作,读操作时不能写操作,保证拉取增量注册表时获取的 recentlyChangedQueue 没变更,recentlyChangedQueue 变更时不给拉取增量注册表

2. invalidateCache()

2.1 源码解析
// AbstractInstanceRegistry.class
private void invalidateCache(String appName, @Nullable String vipAddress, @Nullable String secureVipAddress) {
    // invalidate cache
    // Step1:响应缓存失效
    responseCache.invalidate(appName, vipAddress, secureVipAddress);
}

// ResponseCacheImpl.class
public void invalidate(String appName, @Nullable String vipAddress, @Nullable String secureVipAddress) {
    for (Key.KeyType type : Key.KeyType.values()) {
        for (Version v : Version.values()) {
            // Step2:指定服务名、全量、增量相关的缓存失效
            // 缓存 key 中没有远程 region
            invalidate(
                    new Key(Key.EntityType.Application, appName, type, v, EurekaAccept.full),
                    new Key(Key.EntityType.Application, appName, type, v, EurekaAccept.compact),
                    new Key(Key.EntityType.Application, ALL_APPS, type, v, EurekaAccept.full),
                    new Key(Key.EntityType.Application, ALL_APPS, type, v, EurekaAccept.compact),
                    new Key(Key.EntityType.Application, ALL_APPS_DELTA, type, v, EurekaAccept.full),
                    new Key(Key.EntityType.Application, ALL_APPS_DELTA, type, v, EurekaAccept.compact)
            );
            if (null != vipAddress) {
                invalidate(new Key(Key.EntityType.VIP, vipAddress, type, v, EurekaAccept.full));
            }
            if (null != secureVipAddress) {
                invalidate(new Key(Key.EntityType.SVIP, secureVipAddress, type, v, EurekaAccept.full));
            }
        }
    }
}

// ResponseCacheImpl.class
public void invalidate(Key... keys) {
    // Step3
    for (Key key : keys) {
        logger.debug("Invalidating the response cache key : {} {} {} {}, {}",
                key.getEntityType(), key.getName(), key.getVersion(), key.getType(), key.getEurekaAccept());
				
        // “无远程 regin 缓存 key ”的读写缓存失效
        readWriteCacheMap.invalidate(key);
        // 从 regionSpecificKeys 根据 “无远程 regin 缓存 key ” 取出 “有远程 regin 缓存 key ”
        Collection<Key> keysWithRegions = regionSpecificKeys.get(key);
        if (null != keysWithRegions && !keysWithRegions.isEmpty()) {
            for (Key keysWithRegion : keysWithRegions) {
                logger.debug("Invalidating the response cache key : {} {} {} {} {}",
                        key.getEntityType(), key.getName(), key.getVersion(), key.getType(), key.getEurekaAccept());
                // “有远程 regin 缓存 key ”的读写缓存失效
                readWriteCacheMap.invalidate(keysWithRegion);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值