Nacos heartbeat mechanism repeat sending principle

When I was learning the nacos source code, I just saw a point that has something to do with the ScheduledThreadPoolExecutor recorded yesterday, so record this point

When nacos registers for the service, it will send the heartbeat regularly. When sending the heartbeat, it calls the ScheduledThreadPoolExecutor.schedule() method. In yesterday’s notes, there is a record. This method is actually only called once. ScheduledThreadPoolExecutor also provides The two loops repeatedly call the task at a fixed time, but nacos did not use it. Instead, it used the schedule method. How to achieve repeated heartbeat sending? Call recursively in a loop. . .

Because the so-called heartbeat mechanism of nacos is actually nacos-client periodically sends requests to nacos-server, telling the server that the current service is normal, so it must be called repeatedly at regular intervals.

/**
 * Add beat information.
 * 添加心跳线程,需要注意的是,这里只会发送一次心跳,但是在run方法中,会重复调用schedule方法
 * @param serviceName service name
 * @param beatInfo    beat information
 */
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
	if ((existBeat = dom2Beat.remove(key)) != null) {
    
    
		existBeat.setStopped(true);
	}
	dom2Beat.put(key, beatInfo);
	/**
	 * 这个schedule只会发送一次心跳
	 */
	executorService.schedule(new BeatTask(beatInfo), beatInfo.getPeriod(), TimeUnit.MILLISECONDS);
	MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
}

The following method is the run method of BeatTask. That is to say, when the thread pool is called, it actually executes the run method of BeatTask.
You can see that in the run method, it is a series of processing on the results returned by the heartbeat. The core code for repeating sending heartbeats is in the last line, calling the executorService.schedule() method again

@Override
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);
}

So the simple point: when nacos sends a heartbeat, it will call the schedule method. In the task to be executed by the schedule, if the heartbeat is sent normally, the schedule method will be called again

There is a question to consider here: Why doesn't nacos use a thread pool that executes regularly? For example: scheduleAtFixedRate or scheduleWithFixedDelay?

I began to think that it is possible that nacos will no longer call the schedule method for repeated calls when the server heartbeat interface returns an exception, but in the actual code, I can’t find where the thread execution is aborted, so I still have questions. Place, I also hope that some big guys know the reason, under the guidance

Guess you like

Origin blog.csdn.net/CPLASF_/article/details/112104316