Nacos源码解读03——管理元数据

监听元数据事件

NamingMetadataManager

    @Override
    public void onEvent(Event event) {
         //实例元数据
        if (event instanceof MetadataEvent.InstanceMetadataEvent) {
            handleInstanceMetadataEvent((MetadataEvent.InstanceMetadataEvent) event);
         //服务元数据   
        } else if (event instanceof MetadataEvent.ServiceMetadataEvent) {
            handleServiceMetadataEvent((MetadataEvent.ServiceMetadataEvent) event);
        } else {
        //服务端断开事件
            handleClientDisconnectEvent((ClientEvent.ClientDisconnectEvent) event);
        }
    }

实例元数据事件处理

    private void handleInstanceMetadataEvent(MetadataEvent.InstanceMetadataEvent event) {
        //获取服务信息
        Service service = event.getService();
        //获取metadataId 
        String metadataId = event.getMetadataId();
        if (containInstanceMetadata(service, metadataId)) {
            //过期元数据处理
            updateExpiredInfo(event.isExpired(),
                    ExpiredMetadataInfo.newExpiredInstanceMetadata(event.getService(), event.getMetadataId()));
        }
    }

判断是否包含元数据

    public boolean containInstanceMetadata(Service service, String metadataId) {
        return instanceMetadataMap.containsKey(service) && instanceMetadataMap.get(service).containsKey(metadataId);
    }

操作元数据信息

    private final Set<ExpiredMetadataInfo> expiredMetadataInfos;
    
    private void updateExpiredInfo(boolean expired, ExpiredMetadataInfo expiredMetadataInfo) {
         // 添加或移除过期的实例元数据
        if (expired) {
            expiredMetadataInfos.add(expiredMetadataInfo);
        } else {
            expiredMetadataInfos.remove(expiredMetadataInfo);
        }
    }

元数据处理操作

@Component
public class NamingMetadataManager extends SmartSubscriber {
    //维护过期的元数据信息 包括服务和实例的
    private final Set<ExpiredMetadataInfo> expiredMetadataInfos;
    //维护服务的元数据
    private ConcurrentMap<Service, ServiceMetadata> serviceMetadataMap;
    //维护实例的元数据
    private ConcurrentMap<Service, ConcurrentMap<String, InstanceMetadata>>     
      instanceMetadataMap;
    
    private static final int INITIAL_CAPACITY = 1;
    
    public NamingMetadataManager() {
        //1<<10 = 1024
        serviceMetadataMap = new ConcurrentHashMap<>(1 << 10);
        instanceMetadataMap = new ConcurrentHashMap<>(1 << 10);
        expiredMetadataInfos = new ConcurrentHashSet<>();
        //向NotifyCenter注册自己 这块等后面讲到统一事件中心再详细讲解
        //此处略过
        NotifyCenter.registerSubscriber(this, 
               NamingEventPublisherFactory.getInstance());
    }
    
    //是否包括给服务的元数据
    public boolean containServiceMetadata(Service service) {
        return serviceMetadataMap.containsKey(service);
    }
    
    //是否包含实例的运输局
    public boolean containInstanceMetadata(Service service, String metadataId) {
        return instanceMetadataMap.containsKey(service) &&             
         instanceMetadataMap.get(service).containsKey(metadataId);
    }
    
    //查询服务的元数据
    public Optional<ServiceMetadata> getServiceMetadata(Service service) {
        return Optional.ofNullable(serviceMetadataMap.get(service));
    }
    
   //查询实例的元数据
    public Optional<InstanceMetadata> getInstanceMetadata(Service service, String 
         metadataId) {
        ConcurrentMap<String, InstanceMetadata> instanceMetadataMapForService = 
          instanceMetadataMap.get(service);
        if (null == instanceMetadataMapForService) {
            return Optional.empty();
        }
        return Optional.ofNullable(instanceMetadataMapForService.get(metadataId));
    }
    
   //更新服务的元数据 看到这里应该明白为什么update 和 add 都是调用这个方法了
   //新增server的版本号
    public void updateServiceMetadata(Service service, ServiceMetadata serviceMetadata) 
    {
        service.incrementRevision();
        serviceMetadataMap.put(service, serviceMetadata);
    }
   //更新实例元数据
   //实例元数据是再server为key的子map中 如果子map不存在就new一个
    public void updateInstanceMetadata(Service service, String metadataId, 
       InstanceMetadata instanceMetadata) {
        if (!instanceMetadataMap.containsKey(service)) {
            instanceMetadataMap.putIfAbsent(service, new ConcurrentHashMap<> 
            (INITIAL_CAPACITY));
        }
        instanceMetadataMap.get(service).put(metadataId, instanceMetadata);
    }
    
    /**
     * Remove service metadata.
     *
     * @param service service
     */
    public void removeServiceMetadata(Service service) {
        serviceMetadataMap.remove(service);
        expiredMetadataInfos.remove(ExpiredMetadataInfo.newExpiredServiceMetadata(service));
    }
    
     //移除服务下的某个实例元数据
     //如果给服务下么有么有任务实例就删除服务的元数据
    public void removeInstanceMetadata(Service service, String metadataId) {
        ConcurrentMap<String, InstanceMetadata> instanceMetadataMapForService = instanceMetadataMap.get(service);
        instanceMetadataMapForService.remove(metadataId);
        if (instanceMetadataMapForService.isEmpty()) {
            serviceMetadataMap.remove(service);
        }
        expiredMetadataInfos.remove(ExpiredMetadataInfo.newExpiredInstanceMetadata(service, metadataId));
    }
    
   //从当前的serviceMetadataMap创建快照
   //在导出快照的时候crud是不允许操作的 这个通过前面讲的读写锁来控制
    public Map<Service, ServiceMetadata> getServiceMetadataSnapshot() {
        ConcurrentMap<Service, ServiceMetadata> result = new ConcurrentHashMap<>                
        (serviceMetadataMap.size());
        result.putAll(serviceMetadataMap);
        return result;
    }
    
      //从当前的instanceMetadataMap创建快照
      //在导出快照的时候cud是不允许操作的 这个通过前面讲的读写锁来控制
      //导出时完毕不影响查询操作 
   public Map<Service, ConcurrentMap<String, InstanceMetadata>> 
        getInstanceMetadataSnapshot() {
        ConcurrentMap<Service, ConcurrentMap<String, InstanceMetadata>> result = new 
             ConcurrentHashMap<>(
                instanceMetadataMap.size());
        result.putAll(instanceMetadataMap);
        return result;
    }
    
    //加载服务的元数据快照
    //加载时不可以做cud操作同导出快照一样都是由读写锁控制
    //加载时完毕不影响查询操作
    //最后清空老的数据
    public void loadServiceMetadataSnapshot(ConcurrentMap<Service, ServiceMetadata> 
          snapshot) {
        for (Service each : snapshot.keySet()) {
            ServiceManager.getInstance().getSingleton(each);
        }
        ConcurrentMap<Service, ServiceMetadata> oldSnapshot = serviceMetadataMap;
        serviceMetadataMap = snapshot;
        oldSnapshot.clear();
    }
    
    //加载实例数据 同上
    public void loadInstanceMetadataSnapshot(ConcurrentMap<Service, 
             ConcurrentMap<String, InstanceMetadata>> snapshot) {
        ConcurrentMap<Service, ConcurrentMap<String, InstanceMetadata>> oldSnapshot = 
        instanceMetadataMap;
        instanceMetadataMap = snapshot;
        oldSnapshot.clear();
    }
    
    public Set<ExpiredMetadataInfo> getExpiredMetadataInfos() {
        return expiredMetadataInfos;
    }
    
   //监听元数据变更事件及客户端断开事件
    @Override
    public List<Class<? extends Event>> subscribeTypes() {
        List<Class<? extends Event>> result = new LinkedList<>();
        result.add(MetadataEvent.InstanceMetadataEvent.class);
        result.add(MetadataEvent.ServiceMetadataEvent.class);
        result.add(ClientEvent.ClientDisconnectEvent.class);
        return result;
    }
    
    //处理事件
    @Override
    public void onEvent(Event event) {
        if (event instanceof MetadataEvent.InstanceMetadataEvent) {
            handleInstanceMetadataEvent((MetadataEvent.InstanceMetadataEvent) event);
        } else if (event instanceof MetadataEvent.ServiceMetadataEvent) {
            handleServiceMetadataEvent((MetadataEvent.ServiceMetadataEvent) event);
        } else {
            handleClientDisconnectEvent((ClientEvent.ClientDisconnectEvent) event);
        }
    }
    
    //客户端delete后 找到它所有发布的服务实例
    //从InstancePublishInfo中metadataId, 此处回想下之前讲的的Client对象时管理什么的
    //如果元数据管理器中有metadataId的数据就移除掉
    private void handleClientDisconnectEvent(ClientEvent.ClientDisconnectEvent event) {
        for (Service each : event.getClient().getAllPublishedService()) {
            String metadataId = 
              event.getClient().getInstancePublishInfo(each).getMetadataId();
            if (containInstanceMetadata(each, metadataId)) {
                updateExpiredInfo(true, 
                   ExpiredMetadataInfo.newExpiredInstanceMetadata(each, metadataId));
            }
        }
    }
    
    //只有包含才更新
    //注意不包含的情况不能本地添加 因为要保证集群的数据一致性
    //这里更新并不是更新元数据内容 而是根据服务的上下线 判断要不要加上元数据的过期信息
    private void handleServiceMetadataEvent(MetadataEvent.ServiceMetadataEvent event) {
        Service service = event.getService();
        if (containServiceMetadata(service)) {
            updateExpiredInfo(event.isExpired(), 
            ExpiredMetadataInfo.newExpiredServiceMetadata(service));
        }
    }
    
    //只有包含才更新
    //注意不包含的情况不能本地添加 因为要保证集群的数据一致性
    //这里更新并不是更新元数据内容 而是根据服务的上下线 判断要不要加上元数据的过期信息
    private void handleInstanceMetadataEvent(MetadataEvent.InstanceMetadataEvent event) 
     {
        Service service = event.getService();
        String metadataId = event.getMetadataId();
        if (containInstanceMetadata(service, metadataId)) {
            updateExpiredInfo(event.isExpired(),
                    ExpiredMetadataInfo.newExpiredInstanceMetadata(event.getService(), 
                    event.getMetadataId()));
        }
    }
    
    //服务下线或者客户端delete掉后expired 值为true
    //服务上线后expired为false
    private void updateExpiredInfo(boolean expired, ExpiredMetadataInfo 
         expiredMetadataInfo) {
        if (expired) {
            expiredMetadataInfos.add(expiredMetadataInfo);
        } else {
            expiredMetadataInfos.remove(expiredMetadataInfo);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值