Nacos - 客户端注册中提到了心跳续约。

public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {    String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);    if (instance.isEphemeral()) {        // 封装心跳信息        BeatInfo beatInfo = beatReactor.buildBeatInfo(groupedServiceName, instance);        // 开启定时工作续约        beatReactor.addBeatInfo(groupedServiceName, beatInfo);    }    serverProxy.registerService(groupedServiceName, groupName, instance);}

BeatReactor#addBeatInfo

把心跳工作放入线程池。

public void addBeatInfo(String serviceName, BeatInfo beatInfo) {    NAMING_LOGGER.info("[BEAT] adding beat: {} to beat map.", beatInfo);    String key = buildKey(serviceName, beatInfo.getIp(), beatInfo.getPort());    BeatInfo existBeat = null;    //fix #1733    // 移除旧的BeatInfo    if ((existBeat = dom2Beat.remove(key)) != null) {        existBeat.setStopped(true);    }    //存入dom2Beat    dom2Beat.put(key, beatInfo);    // 开启定时工作    executorService.schedule(new BeatTask(beatInfo), beatInfo.getPeriod(), TimeUnit.MILLISECONDS);    MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());}

BeatReactor.BeatTask#run

向服务器发送心跳,如果没有心跳信息,则从新注册。

public void run() {        if (beatInfo.isStopped()) {            return;        }        long nextTime = beatInfo.getPeriod();        try {            // 向服务器发送心跳            JsonNode result = serverProxy.sendBeat(beatInfo, BeatReactor.this.lightBeatEnabled);            // 获取下一次发送的间隔时间            long interval = result.get("clientBeatInterval").asLong();            boolean lightBeatEnabled = false;            if (result.has(CommonParams.LIGHT_BEAT_ENABLED)) {                lightBeatEnabled = result.get(CommonParams.LIGHT_BEAT_ENABLED).asBoolean();            }            BeatReactor.this.lightBeatEnabled = lightBeatEnabled;            if (interval > 0) {                nextTime = interval;            }            int code = NamingResponseCode.OK;            if (result.has(CommonParams.CODE)) {                code = result.get(CommonParams.CODE).asInt();            }            // 发现没有心跳信息,则从新注册            if (code == NamingResponseCode.RESOURCE_NOT_FOUND) {                Instance instance = new Instance();                instance.setPort(beatInfo.getPort());                instance.setIp(beatInfo.getIp());                instance.setWeight(beatInfo.getWeight());                instance.setMetadata(beatInfo.getMetadata());                instance.setClusterName(beatInfo.getCluster());                instance.setServiceName(beatInfo.getServiceName());                instance.setInstanceId(instance.getInstanceId());                instance.setEphemeral(true);                try {                    serverProxy.registerService(beatInfo.getServiceName(),                            NamingUtils.getGroupName(beatInfo.getServiceName()), instance);                } catch (Exception ignore) {                }            }        } catch (NacosException ex) {            NAMING_LOGGER.error("[CLIENT-BEAT] failed to send beat: {}, code: {}, msg: {}",                    JacksonUtils.toJson(beatInfo), ex.getErrCode(), ex.getErrMsg());                    }        executorService.schedule(new BeatTask(beatInfo), nextTime, TimeUnit.MILLISECONDS);    }

客户端总结