文章目录
- 前言
- 一、服务端推送配置信息,客户端的处理
- [总结:Nacos 配置中心客户端处理服务端推送配置信息的流程解析](#总结:Nacos 配置中心客户端处理服务端推送配置信息的流程解析)
前言
Nacos配置中心,对于页面上用户操作的配置信息,实际上是使用了推拉结合的模式。
- 服务端将配置信息推送到客户端。
- 客户端主动向服务端发起请求拉取配置信息。
本篇介绍服务端将配置信息推送到客户端,客户端的处理方式
一、服务端推送配置信息,客户端的处理
1.1、客户端获取服务端请求,发布事件
当用户在页面上对配置信息进行操作时,会调用服务端 的ConfigController
的publishConfig
。最终还会将配置信息推送到客户端:
该请求会被客户端的ClientWorker.ConfigRpcTransportClient#initRpcClientHandler
接收:
分为了两步操作:
- 向
RpcClient
的serverRequestHandlers
集合中注册一个Handler。

- 实例化该Handler的对象,在合适的时机调用。
在实例化ServerRequestHandler
对象,重写的requestReply
方法中,先是通过组合dataId
、group
、tenant
生成一个唯一标识配置项的groupKey
,然后去缓存中查找,如果缓存中存在对应配置:
- 同步锁定该
CacheData
实例; - 更新最后修改时间戳;
- 标记客户端缓存与服务端不同步;
- 触发监听器通知。
CacheData
是Nacos客户端承载配置信息的对象,存放了基本信息:
在notifyListenConfig
方法中,是向listenExecutebell
队列中放入了一个空的Object对象,而非具体的事件**
1.2、客户端启动时,轮询监听事件
listenExecutebell
队列中的元素何时被消费?
在spring-cloud-starter-alibaba-nacos-config
的jar包中的spring.factories
文件中,有NacosConfigBootstrapConfiguration
类,是Nacos配置中心启动 的相关配置。
向Spring容器中条件装配了三个Bean。其中和本文中功能相关的,是
NacosConfigManager
(Nacos配置管理者)。
在NacosConfigManager
的构造中,实际上是要给NacosConfigManager
类的两个属性赋值。
- nacosConfigProperties代表了配置文件中的信息。
- service是配置管理 的核心接口,定义了客户端与配置中心交互的主要 API,例如获取配置、发布配置、监听配置变更等操作。这里赋值给它的是其子类
NacosConfigService
。

尝试通过反射创建NacosConfigService
的实例。(通过NacosConfigService的有参构造,传入properties参数)
又会去创建ClientWorker
的实例:
创建ClientWorker
的实例的关键代码:
- 实例化了
ConfigRpcTransportClient
,它是ClientWorker
的一个内部类。 - 调用
ConfigRpcTransportClient
的start
方法。

start
方法,最终会调用到ConfigRpcTransportClient
的startInternal
,同样是在线程池中开启了一个死循环,当线程池存活时,就会一直执行里面的逻辑。**这里的listenExecutebell就是notifyListenConfig
方法中放入事件的那个阻塞队列,每隔5s从队列中获取元素,获取不到就会陷入阻塞。
这里获取到的不是具体的事件,而是一个空的Object对象。这个 Object 实际是一个"唤醒标记",而不是用来传递事件数据的。(设计精髓)
上面的
NacosConfigBootstrapConfiguration
类。是在SpringBoot整合了Nacos,启动时利用自动配置机制完成的。所以这一块的设计和Nacos注册中心服务端获取客户端的注册信息、以及配置中心服务端消费者消费事件,向客户端发送通知 这两者的设计,是同样的道理。都是在程序启动的过程中,先初始化一个线程去轮询监听 + 阻塞队列。在相应的请求到达时,从队列中获取元素进行处理。
1.3、客户端订阅事件并处理
当从listenExecutebell
中获取到标记后,就会进入executeConfigListen
的逻辑,真正地去进行事件的处理,关键代码在于refreshContentAndCheck
:
在该方法中,首先会从缓存配置信息的Map中,获取该groupKey
对应的缓存信息,然后再次调用重载的refreshContentAndCheck
- 远程获取配置文件
- 对有变化的配置调用对应的监听器去处理

1.3.1、getServerConfig远程获取配置文件
最终调用到的是queryConfig
方法:
- 又会去向服务端发送请求,获取最新的配置。
- 保存到本地(快照)。
服务端接收该请求的是ConfigQueryRequestHandler
的handle
方法:
最终是从磁盘 获取的配置文件,然后响应给客户端的,所以直接改数据库中的配置信息,客户端是感知不到的。
这里为什么要从磁盘获取?服务端不是保存了一份到数据库中吗?
可能是考虑到性能问题,从磁盘获取文件的效率,要高于数据库的IO操作(省去了连接,响应的时间)。
1.3.2、更新文件变更checkListenerMd5

最终会来到safeNotifyListener
,在其中,有两处关键的代码:
利用线程池提交一个job
job中利用listener
的receiveConfigInfo
方法,真正地执行逻辑
选择AbstractSharedListener
的实现:

实际调用的是子类NacosContextRefresher
重写的innerReceive
方法:
- 添加一条配置信息的历史记录(在本地记录一个配置变更历史,并控制记录列表的大小不超过阈值。)
- 发布配置信息的刷新事件 ,对应的监听器是
RefreshEventListener

这里向客户端的内存中保存了一份,如何保证和数据库中历史记录的一致性?
客户端历史记录仅用于本地用途,不参与服务端页面上的历史记录,页面展示的历史记录来源于服务端数据库;
刷新事件与Nacos的动态刷新配置有关。
总结:Nacos 配置中心客户端处理服务端推送配置信息的流程解析
在 Nacos 配置中心中,服务端 在检测到配置内容发生变更后,会客户端推送变更通知。客户端收到推送通知,并不会直接处理变更配置内容,而是通过一系列异步机制完成完整的配置拉取与刷新流程。
客户端接收服务端推送通知
当服务端发起配置变更的推送请求时,客户端内部的 ClientWorker.ConfigRpcTransportClient#initRpcClientHandler
会接收到该请求。客户端在接收到该通知后,并不会立即处理配置内容,而是向内部的阻塞队列 listenExecutebell
中放入一个空的 Object
实例,作为"配置已变更"的标记。
这一设计的核心在于将处理逻辑解耦:推送通知的接收与配置内容的处理并不在同一线程中完成,而是通过队列和监听线程实现异步化与任务排队。
客户端监听线程的启动机制
在客户端启动过程中,Nacos 通过 Spring Boot 的自动配置机制,在 NacosConfigBootstrapConfiguration
中初始化配置环境。该类会创建用于监听配置变化的线程池,启动监听任务。
该监听线程会轮询检查 listenExecutebell
队列,一旦检测到有新元素被放入(即接收到变更标记),便开始配置处理流程。
配置变更处理逻辑
监听线程在检测到配置变更标记后,分两个步骤完成处理:
- 远程拉取最新配置内容并保存快照
客户端会通过远程调用向服务端发起配置查询请求,对应服务端处理类为ConfigQueryRequestHandler#handle
。服务端接收到请求后,会从磁盘读取对应的配置信息,并将结果返回给客户端。客户端收到后,会将配置内容写入本地快照中,用于容灾和本地缓存读取。 - 比对并触发配置变更事件
客户端计算拉取到的配置内容的 MD5,与缓存中的 MD5 进行比对。如果内容发生变化,则会:- 记录一条配置变更历史(仅保存在客户端内存中);
- 触发配置刷新事件,发布到 Spring 上下文中,由
RefreshEventListener
等监听器进行处理。
需要注意的是:客户端本地记录的配置历史仅供本地诊断与调试使用,不会同步到服务端,也不参与页面展示的历史版本信息 。Nacos 控制台页面中展示的历史记录,来源于服务端数据库的 his_config_info
表,由服务端在每次配置发布时自动写入。
架构设计理念
这种设计体现了 Nacos 配置中心架构的核心理念:事件驱动 + 队列解耦 + 监听异步处理 。同时体现 轻推重拉(轻量推送、客户端主动拉取) 的策略
服务端推送的不是配置内容 ,而是变更事件。这个事件就是一个带有定位信息的"标记",客户端基于这个事件再去主动获取配置内容,实现了高效、实时、低耦合的配置同步机制。客户端并不会直接处理服务端推送的配置信息,而是通过监听线程加阻塞队列的方式,将推送转化为本地的"变更信号",再由客户端主动拉取配置、判断差异、触发刷新事件。
字段 | 说明 |
---|---|
dataId |
变更的配置项 ID |
group |
配置所属的分组 |
tenant |
租户信息(多租户场景) |
这种机制与 Nacos 注册中心中的客户端注册/订阅模型具有高度相似性:
- 程序启动时初始化监听线程;
- 使用阻塞队列作为"信号触发器";
- 接收到变更后进行数据拉取和后续处理。
- 客户端不会直接使用服务端推送的配置内容,而是收到通知后主动发起查询;
- 推送仅作为"配置已变更"的标记,通过阻塞队列传递到监听线程;
- 监听线程完成实际配置拉取、MD5 校验、历史记录记录以及刷新事件发布;
- 客户端历史记录仅用于本地用途,控制台页面展示的历史版本来源于服务端数据库;
- 整体设计体现了事件驱动、异步解耦的系统架构思想。