How Nacos Implements Long‑Polling for Config Synchronization

This article explains the inner workings of Nacos' configuration center, detailing the client‑side long‑polling mechanism, the server‑side handling of listener requests, and the key classes and code paths that enable real‑time config updates in microservice environments.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
How Nacos Implements Long‑Polling for Config Synchronization

After introducing Nacos basics and its role as a service registry, this article dives into one of the core principles of the Nacos configuration center: the long‑polling mechanism.

1. Client‑side long‑polling schedule

The process starts from NacosPropertySourceLocator.locate(), which creates a ConfigService instance. The creation flow follows NacosFactory.createConfigService()ConfigFactory.createConfigService(), where reflection instantiates NacosConfigService. Inside NacosConfigService 's constructor, a ClientWorker is created, which starts a scheduled thread pool and launches the long‑polling task.

Long‑polling mechanism diagram
Long‑polling mechanism diagram

The long‑polling task is implemented in LongPollingRunnable.run(). It iterates over cacheMap (an AtomicReference<Map<String, CacheData>>) to check local config changes via checkLocalConfig(). If changes are detected, it triggers notifications. Otherwise, it calls checkUpdateDataIds(), which ultimately invokes checkUpdateConfigStr() and sends a long‑polling HTTP request to /v1/cs/configs/listener using MetricsHttpAgent.httpPost(). The request includes a long timeout (default 30 s). When the server reports changed dataId, getServerConfig() fetches the new content via MetricsHttpAgent.httpGet() from /v1/cs/configs, and the snapshot is saved locally.

ClientWorker initialization
ClientWorker initialization

1.1 Instantiating NacosConfigService via reflection

The factory method uses reflection to create the NacosConfigService object.

1.2 Starting the scheduled long‑polling task

ClientWorker.ClientWorker()

creates two thread pools and schedules the periodic check.

1.3 Checking configuration changes

LongPollingRunnable.run()

splits tasks based on taskId, checks local files under ${user}\nacos\config\, and, if needed, fetches updated configurations from the server.

public static ConfigService createConfigService(Properties properties) throws NacosException {
    //【断点步入】创建 ConfigService
    return ConfigFactory.createConfigService(properties);
}

2. Server‑side long‑polling schedule

The Nacos server receives listener requests via ConfigController.listener(). The request is processed by ConfigServletInner.doPollingConfig(), which delegates to LongPollingService.addLongPollingClient(). This method wraps the client request into a ClientPolling object and submits it to a scheduler.

Server listener flow
Server listener flow

The core execution occurs in ClientLongPolling.run(), which holds the request for up to 30 s. If no configuration change occurs, the response is delayed; otherwise, the server returns the changed dataId, group, and tenant immediately.

Long‑polling execution
Long‑polling execution

When a configuration change is detected on the server, a LocalDataChangeEvent is published. Prior to Nacos 1.3.1, LongPollingService.onEvent() handled the event; from 1.3.2 onward, a Subscriber.onEvent() processes it, triggering a DataChangeTask that fetches the updated config and sends the response back to the client.

Event handling after config change
Event handling after config change

3. Summary of the source code structure

The following diagram outlines the main call chain on both client and server sides:

NacosPropertySourceLocator.locate() – initializes ConfigService NacosConfigService.NacosConfigService() – constructor sets up workers

Executors.newScheduledThreadPool() – creates thread pools

ClientWorker.checkConfigInfo() – periodic check for changes

ClientWorker.checkLocalConfig() – local file comparison

ClientWorker.checkUpdateDataIds() – server‑side change detection

ClientWorker.getServerConfig() – fetches updated config

MetricsHttpAgent.httpPost() – long‑polling request to /listener MetricsHttpAgent.httpGet() – fetches config from /configs LongPollingRunnable.run() – runs client‑side polling thread

ConfigController.listener() – server receives request

LongPollingService.addLongPollingClient() – registers client polling

ClientLongPolling.run() – server‑side polling execution

DataChangeTask.run() – processes config change events

These components together realize Nacos' efficient long‑polling mechanism, ensuring that configuration updates are propagated to clients with minimal latency while avoiding excessive polling traffic.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavamicroservicesNacosconfiguration centerlong polling
Code Ape Tech Column
Written by

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

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.