Understanding Nacos Configuration Center: Pull Model, Long Polling, and Source Code Analysis
This article explains how Nacos configuration center works, clarifies that it uses a client‑initiated pull (long‑polling) model rather than push, and walks through key client and server source code components—including cacheMap, listeners, long‑polling handling, and configuration change notification – to help developers and interviewees master its internals.
Nacos, an open‑source service discovery and configuration management tool from Alibaba, is widely used in micro‑service architectures. When configuring Nacos as a configuration center, the data exchange follows a client‑initiated pull model, not a server push.
Configuration Center Basics – It centralizes configuration files (YAML, properties, XML, etc.) so that applications can dynamically sense changes without restarting. This is essential in micro‑service environments where dozens or hundreds of services share common settings.
Push vs Pull Model – In the push model the server maintains a TCP long‑connection and pushes updates instantly, but it suffers from potential "dead" connections and requires heartbeat mechanisms. In the pull model the client periodically requests configuration (often via long polling), which is simpler but can introduce latency if not optimized.
Long Polling in Nacos – Nacos implements a long‑polling pull model. The client sends a request that the server holds for up to 30 seconds (actually 29.5 seconds after a 500 ms safety margin). If the configuration changes, the server immediately responds; otherwise it returns after the timeout, and the client re‑issues the request.
Client‑Side Implementation
The client code resides in the nacos-client module, with NacosConfigService as the main entry point. A crucial data structure is cacheMap , an AtomicReference<Map<String, CacheData>> that stores CacheData objects keyed by a concatenated groupKey (dataId + group + tenant). The client first reads a local snapshot; if absent, it performs an HTTP pull via getConfig or getConfigAndSignListener . Listener registration updates the CacheData and schedules a long‑polling task.
private final AtomicReference
> cacheMap = new AtomicReference<>(new HashMap<>());
@Override
public String getConfig(String dataId, String group, long timeoutMs) throws NacosException {
return getConfigInner(namespace, dataId, group, timeoutMs);
}
@Override
public String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener) throws NacosException {
String content = getConfig(dataId, group, timeoutMs);
worker.addTenantListenersWithContent(dataId, group, content, Arrays.asList(listener));
return content;
}Listeners are wrapped in ManagerListenerWrap , which stores the last known MD5 hash to detect changes. When the server notifies a change, safeNotifyListener is invoked to deliver the new configuration to the client.
Server‑Side Implementation
The server side lives in the nacos-config module, primarily in ConfigController . It exposes /v1/cs/configs/listener for long‑polling. The request header Long-Pulling-Timeout determines whether the request is short or long polling. The LongPollingService compares the client’s MD5 with the server’s current MD5; a mismatch triggers an immediate response, otherwise the request is suspended as a ClientLongPolling task in a scheduler.
ConfigExecutor.executeLongPolling(new ClientLongPolling(asyncContext, clientMd5Map, ip, probeRequestSize, timeout, appName, tag));When a configuration is updated via publishConfig , a ConfigDataChangeEvent is fired. LongPollingService subscribes to this event and runs a DataChangeTask that scans all suspended long‑polling tasks, finds those matching the changed groupKey , and completes their asyncContext to push the new data.
ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent(false, dataId, group, tenant, time.getTime()));Demo Code – A simple Java demo shows how to retrieve a configuration, register a listener, publish a new value, and observe the immediate callback via the long‑polling pull mechanism.
public static void main(String[] args) throws NacosException, InterruptedException {
String serverAddr = "localhost";
String dataId = "test";
String group = "DEFAULT_GROUP";
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);
ConfigService configService = NacosFactory.createConfigService(properties);
String content = configService.getConfig(dataId, group, 5000);
System.out.println(content);
configService.addListener(dataId, group, new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
System.out.println("数据变更 receive:" + configInfo);
}
@Override
public Executor getExecutor() { return null; }
});
boolean isPublishOk = configService.publishConfig(dataId, group, "我是新配置内容~");
System.out.println(isPublishOk);
Thread.sleep(3000);
content = configService.getConfig(dataId, group, 5000);
System.out.println(content);
}The result demonstrates that after publishing a new configuration, the client instantly receives the change despite using a pull‑based long‑polling approach.
Conclusion – Nacos’s configuration center relies on a client‑pull long‑polling mechanism, with sophisticated server‑side handling to minimize latency and resource usage. Understanding the key classes ( cacheMap , CacheData , LongPollingService , DataChangeTask ) provides a solid foundation for both interview preparation and practical implementation.
Wukong Talks Architecture
Explaining distributed systems and architecture through stories. Author of the "JVM Performance Tuning in Practice" column, open-source author of "Spring Cloud in Practice PassJava", and independently developed a PMP practice quiz mini-program.
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.