zoukankan      html  css  js  c++  java
  • nacos 服务的实例变化

    Service 实现了 RecordListener 接口,在 service 的 instance 发生变化时,调用 onChange 方法。

    nacos 在创建 service 对象的时候,会把 service 放入 DistroConsistencyServiceImpl#listeners 中(这里只考虑服务的临时实例)

    // com.alibaba.nacos.naming.core.ServiceManager#putServiceAndInit
    private void putServiceAndInit(Service service) throws NacosException {
        putService(service);
        service.init();
        consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service);
        consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service);
        Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJSON());
    }

    当 service 有新的实例注册时

    1. 修改内存中的数据,推送服务实例变化给 nacos 客户端

    Notifier 增加 Task

    // com.alibaba.nacos.naming.consistency.ephemeral.distro.DistroConsistencyServiceImpl#onPut
    public void onPut(String key, Record value) {
        // 更新 Datum
        if (KeyBuilder.matchEphemeralInstanceListKey(key)) {
            Datum<Instances> datum = new Datum<>();
            datum.value = (Instances) value;
            datum.key = key;
            datum.timestamp.incrementAndGet();
            dataStore.put(key, datum);
        }
    
        if (!listeners.containsKey(key)) {
            return;
        }
    
        // 创建 task 放入队列
        notifier.addTask(key, ApplyAction.CHANGE);
    }

    从队列取出任务执行,触发 Service.onChange

    // com.alibaba.nacos.naming.core.Service#onChange

    1.1 更新 Service 对象的内容
    1.2 推送变化给 udp 客户端

    // com.alibaba.nacos.naming.push.PushService#serviceChanged
    public void serviceChanged(Service service) {
        // merge some change events to reduce the push frequency:
        if (futureMap.containsKey(UtilsAndCommons.assembleFullServiceName(service.getNamespaceId(), service.getName()))) {
            return;
        }
    
        this.applicationContext.publishEvent(new ServiceChangeEvent(this, service));
    }
    
    // com.alibaba.nacos.naming.push.PushService#onApplicationEvent

    客户端在查询服务实例的时候,如果提供 udp 端口,则 server 会创建 udpClient,当服务实例发生变化时,推送更新

    // com.alibaba.nacos.naming.push.PushService#addClient

    udp 推送实例变化,是一个思路,首先确保 nacos 主动连接服务实例网络通畅,同时通信双方需要协调好数据包大小。 

    2. 当前 nacos 要同步数据给其他 nacos 节点

    // com.alibaba.nacos.naming.consistency.ephemeral.distro.DataSyncer#submit
    // com.alibaba.nacos.naming.misc.NamingProxy#syncData

    URL 是 /v1/ns/distro/datum

    处理请求是 DistroController#onSyncDatum

    3. nacos 节点之间还有一种定时同步数据的方式

    // com.alibaba.nacos.naming.consistency.ephemeral.distro.DataSyncer.TimedSync

    当前 nacos 节点把自己负责的 service 的 key 和实例的 md5 签名发送给其他 nacos 节点。

    其他节点收到 key 和签名后,对比本地数据,筛选出需要删除和更新的服务 

    // com.alibaba.nacos.naming.controllers.DistroController#syncChecksum

    需要删除的直接删除,需要更新的,发起更新请求

    // com.alibaba.nacos.naming.misc.NamingProxy#getData

    所以会有多个 nacos 节点推送 udp 报文给同一个客户端吗?

  • 相关阅读:
    Golang-单元测试
    Golang-Json序列化和反序列化
    Golang-文件操作
    Golang-demo
    Golang-demo练习
    Golang-类型断言
    Golang-面向对象编程三大特性-多态
    Golang-接口(interface)
    Golang-面向对象编程三大特性-继承、多重继承
    块状元素和内联元素 【转】
  • 原文地址:https://www.cnblogs.com/allenwas3/p/12115863.html
Copyright © 2011-2022 走看看