Deep Dive into Nacos Service Registration and Discovery Mechanisms
This article provides a detailed analysis of Nacos as a service registry, covering its architecture, registration and discovery processes, health‑checking, Raft‑based consistency, Spring Cloud integration, and practical code examples for developers building micro‑service systems.
1. Introduction to Nacos
Nacos combines a registration center and a configuration center to solve service registration, discovery, and dynamic configuration in micro‑service architectures. It supports DNS and RPC‑based discovery, health monitoring, dynamic configuration, dynamic DNS, and metadata management.
2. Nacos Registration Center Implementation
2.1 Architecture Diagram
The Nacos cluster consists of Provider APP, Consumer APP, Name Server (VIP/DNS routing), Nacos Server (OpenAPI, Config Service, Naming Service, Raft consistency protocol), and Nacos Console.
Key points:
Provider APP registers services via VIP to the Nacos Server cluster.
Nacos Server synchronizes data across nodes using the Raft algorithm.
2.2 Registration Process
When a service starts, Spring Cloud’s AutoServiceRegistration (implemented by NacosAutoServiceRegistration ) listens for WebServerInitializedEvent . Upon event, it invokes NacosServiceRegistry.register() , which ultimately calls the Nacos client SDK’s NamingService.registerInstance() .
public void register(Registration registration) {
if (StringUtils.isEmpty(registration.getServiceId())) {
log.warn("No service to register for nacos client...");
} else {
String serviceId = registration.getServiceId();
String group = this.nacosDiscoveryProperties.getGroup();
Instance instance = this.getNacosInstanceFromRegistration(registration);
try {
this.namingService.registerInstance(serviceId, group, instance);
log.info("nacos registry, {} {} {}:{} register finished", group, serviceId, instance.getIp(), instance.getPort());
} catch (Exception e) {
log.error("nacos registry, {} register failed...", serviceId, e);
ReflectionUtils.rethrowRuntimeException(e);
}
}
}The registration method performs two main actions:
Creates a heartbeat ( beatReactor.addBeatInfo() ) to monitor service health.
Calls serverProxy.registerService() to send an OpenAPI request that stores instance metadata (IP, port, weight, etc.) in Nacos.
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
Map
params = new HashMap(9);
params.put("namespaceId", this.namespaceId);
params.put("serviceName", serviceName);
params.put("groupName", groupName);
params.put("clusterName", instance.getClusterName());
params.put("ip", instance.getIp());
params.put("port", String.valueOf(instance.getPort()));
params.put("weight", String.valueOf(instance.getWeight()));
params.put("enable", String.valueOf(instance.isEnabled()));
params.put("healthy", String.valueOf(instance.isHealthy()));
params.put("ephemeral", String.valueOf(instance.isEphemeral()));
params.put("metadata", JSON.toJSONString(instance.getMetadata()));
this.reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, "POST");
}2.3 Health‑Check Mechanism
The heartbeat is scheduled with executorService.schedule() to send a packet every few seconds. If the server does not respond, the instance is considered unhealthy and will not be registered.
public void addBeatInfo(String serviceName, BeatInfo beatInfo) {
String key = this.buildKey(serviceName, beatInfo.getIp(), beatInfo.getPort());
BeatInfo existBeat = this.dom2Beat.remove(key);
if (existBeat != null) {
existBeat.setStopped(true);
}
this.dom2Beat.put(key, beatInfo);
this.executorService.schedule(new BeatReactor.BeatTask(beatInfo), beatInfo.getPeriod(), TimeUnit.MILLISECONDS);
MetricsMonitor.getDom2BeatSizeMonitor().set((double) this.dom2Beat.size());
}3. Nacos Service Discovery
Discovery is triggered when a consumer makes a remote call (e.g., via OpenFeign). The NacosServerList.getServers() method obtains instances by calling NacosNamingService.selectInstances() , which may retrieve data from a local cache (subscription mode) or directly from the server.
public List
selectInstances(String serviceName, String groupName, boolean healthy) throws NacosException {
return this.selectInstances(serviceName, groupName, healthy, true);
}The HostReactor maintains three maps:
serviceInfoMap – local cache of service metadata.
updatingMap – tracks services currently being refreshed.
futureMap – stores scheduled update tasks.
private final Map
serviceInfoMap;
private Map
updatingMap;
private final Map
> futureMap;When a service is not in the cache, updateServiceNow() fetches it immediately; otherwise, scheduleUpdateIfAbsent() creates a periodic task (default every 10 seconds) to keep the cache fresh.
3.1 Discovery Flow Summary
Feign client triggers NacosServerList.getServers() with the service name.
NacosNamingService.selectInstances() queries the local HostReactor or the server.
Instance list is converted to NacosServer objects and returned to the caller.
Cache updates are handled asynchronously via scheduleUpdateIfAbsent() and updateServiceNow() .
4. Conclusion
Nacos provides a robust registration and discovery solution for Spring Cloud micro‑services. By leveraging event‑driven registration, Raft‑based consistency, heartbeat health checks, and a local cache with periodic synchronization, it ensures high availability and fast service lookup even when some instances fail.
For further reading, the author offers PDF collections on Spring Cloud, Spring Boot, and MyBatis via the “Java后端面试官” public account.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.