10. Nacos服务端-集群同步状态

Nacos服务端-集群同步状态

Nacos-server 搭建集群时,集群中的每个server要互相同步状态,以便及时感知集群中的节点状态情况,前面几章中很多地方有 Responsible(servicename) 是否对 service负责 的判断,就需要用到节点的数量

本章代码入口在 ServerListManager 的初始化方法中,有两个线程会执行,分别是 ServerStatusReportServerInfoUpdater

image-20231202021657572

ServerStatusReporter
public void run() {
    try {

        if (EnvUtil.getPort() <= 0) {
            return;
        }

        // 获取机器的核心数 / 2
        int weight = Runtime.getRuntime().availableProcessors() / 2;
        // 如果是1核,weight = 0,设置为1
        if (weight <= 0) {
            weight = 1;
        }

        long curTime = System.currentTimeMillis();
        // 构造一串字符串
        String status = LOCALHOST_SITE + "#" + EnvUtil.getLocalAddress() + "#" + curTime + "#" + weight
                + "\r\n";

        // 获取所有的server信息
        List<Member> allServers = getServers();
		// 如果不包含本server, return
        if (!contains(EnvUtil.getLocalAddress())) {
            Loggers.SRV_LOG.error("local ip is not in serverlist, ip: {}, serverlist: {}",
                    EnvUtil.getLocalAddress(), allServers);
            return;
        }
		
        if (allServers.size() > 0 && !EnvUtil.getLocalAddress()
                .contains(IPUtil.localHostIP())) {
            // 遍历所有的server
            for (Member server : allServers) {
                // 排除本server
                if (Objects.equals(server.getAddress(), EnvUtil.getLocalAddress())) {
                    continue;
                }

                // This metadata information exists from 1.3.0 onwards "version"
                if (server.getExtendVal(MemberMetaDataConstants.VERSION) != null) {
                    Loggers.SRV_LOG
                            .debug("[SERVER-STATUS] target {} has extend val {} = {}, use new api report status",
                                    server.getAddress(), MemberMetaDataConstants.VERSION,
                                    server.getExtendVal(MemberMetaDataConstants.VERSION));
                    continue;
                }

                Message msg = new Message();
                msg.setData(status);

                // 调用其他server接口,这里会调用ServerStatusSynchronizer实现类
                synchronizer.send(server.getAddress(), msg);
            }
        }
    } catch (Exception e) {
        Loggers.SRV_LOG.error("[SERVER-STATUS] Exception while sending server status", e);
    } finally {
        GlobalExecutor
                .registerServerStatusReporter(this, switchDomain.getServerStatusSynchronizationPeriodMillis());
    }

}
public void send(final String serverIP, Message msg) {
    if (StringUtils.isEmpty(serverIP)) {
        return;
    }
    
    final Map<String, String> params = new HashMap<String, String>(2);
    
    params.put("serverStatus", msg.getData());
    
    String url = "http://" + serverIP + ":" + EnvUtil.getPort() + EnvUtil.getContextPath()
            + UtilsAndCommons.NACOS_NAMING_CONTEXT + "/operator/server/status";
    
    if (IPUtil.containsPort(serverIP)) {
        url = "http://" + serverIP + EnvUtil.getContextPath() + UtilsAndCommons.NACOS_NAMING_CONTEXT
                + "/operator/server/status";
    }
    
    try {
        // GET调用/v1/ns/operator/server/status
        HttpClient.asyncHttpGet(url, null, params, new Callback<String>() {
            @Override
            public void onReceive(RestResult<String> result) {
                if (!result.ok()) {
                    Loggers.SRV_LOG.warn("[STATUS-SYNCHRONIZE] failed to request serverStatus, remote server: {}",
                            serverIP);
                }
            }

            @Override
            public void onError(Throwable throwable) {
                Loggers.SRV_LOG.warn("[STATUS-SYNCHRONIZE] failed to request serverStatus, remote server: {}", serverIP, throwable);
            }

            @Override
            public void onCancel() {
    
            }
        });
    } catch (Exception e) {
        Loggers.SRV_LOG.warn("[STATUS-SYNCHRONIZE] failed to request serverStatus, remote server: {}", serverIP, e);
    }
}

再看看调用的这个接口,在 OperatorController

@RequestMapping("/server/status")
public String serverStatus(@RequestParam String serverStatus) {
    serverListManager.onReceiveServerStatus(serverStatus);
    return "ok";
}
public boolean update(Member newMember) {
    Loggers.CLUSTER.debug("member information update : {}", newMember);

    String address = newMember.getAddress();
    // 如果本地serverList不包含该地址
    if (!serverList.containsKey(address)) {
        return false;
    }

    // 更新server信息到serverList
    serverList.computeIfPresent(address, (s, member) -> {
        // 如果新member的状态为DOWN
        if (NodeState.DOWN.equals(newMember.getState())) {
            // 从memberAddressInfos中移除该member的地址
            memberAddressInfos.remove(newMember.getAddress());
        }
        // 判断是否改变信息
        boolean isPublishChangeEvent = MemberUtil.isBasicInfoChanged(newMember, member);
        // 设置最后刷新事件
        newMember.setExtendVal(MemberMetaDataConstants.LAST_REFRESH_TIME, System.currentTimeMillis());
        // 对象赋值 newMember-> member(旧)
        MemberUtil.copy(newMember, member);
        // 是否改变信息
        if (isPublishChangeEvent) {
            // member basic data changes and all listeners need to be notified
            // 发布MembersChangeEvent
            notifyMemberChange();
        }
        return member;
    });

    return true;
}

void notifyMemberChange() {
    NotifyCenter.publishEvent(MembersChangeEvent.builder().members(allMembers()).build());
}
ServerInfoUpdater
public void run() {
    List<Member> members = servers;
    if (members.isEmpty()) {
        return;
    }
    // 轮询获取下一个server
    this.cursor = (this.cursor + 1) % members.size();
    Member target = members.get(cursor);
    if (Objects.equals(target.getAddress(), EnvUtil.getLocalAddress())) {
        return;
    }

    // This metadata information exists from 1.3.0 onwards "version"
    if (target.getExtendVal(MemberMetaDataConstants.VERSION) != null) {
        return;
    }

    // 构造url: /operator/cluster/state
    final String path =
        UtilsAndCommons.NACOS_NAMING_OPERATOR_CONTEXT + UtilsAndCommons.NACOS_NAMING_CLUSTER_CONTEXT
        + "/state";
    final Map<String, String> params = Maps.newHashMapWithExpectedSize(2);
    // 目标server地址
    final String server = target.getAddress();

    try {
        // 发起调用
        String content = NamingProxy.reqCommon(path, params, server, false);
        if (!StringUtils.EMPTY.equals(content)) {
            RaftPeer raftPeer = JacksonUtils.toObj(content, RaftPeer.class);
            if (null != raftPeer) {
                String json = JacksonUtils.toJson(raftPeer);
                Map map = JacksonUtils.toObj(json, HashMap.class);
                target.setExtendVal("naming", map);
                // 更新信息到本地
                memberManager.update(target);
            }
        }
    } catch (Exception ignore) {
        //
    }
}
p.class);
                target.setExtendVal("naming", map);
                // 更新信息到本地
                memberManager.update(target);
            }
        }
    } catch (Exception ignore) {
        //
    }
}
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值