在微服务架构中,服务发现与配置管理的核心诉求是数据一致性与服务可用性的动态平衡。然而由于分布式系统天然面临网络分区(Partition Tolerance,P)的不可控风险,CAP 原则又明确了三者不可兼得的铁律——在必须保障 P 的前提下,系统只能在一致性(Consistency,C)与可用性(Availability,A)之间做出取舍。
Nacos 作为一站式服务治理中间件,其核心创新在于采用双协议协同架构应对差异化场景需求:Raft 协议强化 CP 特性,保障核心数据的强一致性;Distro 协议主打 AP 特性,支撑海量数据的高可用吞吐。Nacos 2.x 进一步通过 gRPC 协议升级、算法底层优化,让双协议的协同效率实现质的飞跃。
CAP 原则、Raft & Distro 协议:分布式系统的取舍逻辑
CAP 原则的本质是分布式系统设计的 “三角约束”:
- 分区容错性(P)是必选项:分布式系统跨节点部署的特性决定了网络故障不可避免,必须保证网络分区场景下系统仍能提供基础服务
- 一致性(C)的核心是 “数据统一”:即分布式系统中所有节点的数据实时保持一致,任意节点读取到的都是最新数据
- 可用性(A)的核心是 “服务持续可用”:即任何合法请求都能在合理时间内获得明确响应,短暂数据不一致可通过异步同步机制修复
基于此,分布式系统的架构选择本质是:在保障 P 的基础上,根据业务优先级选择 “CP 优先” 或 “AP 优先”——这正是 Nacos 双协议架构的设计根基与核心逻辑。
Raft 协议是 Nacos 实现强一致性(CP)的设计规范。而在实现 Raft 规范时,Nacos 引入了 JRaft 库,并在 Nacos 2.x 上进行深度优化,进一步强化了 CP 特性的同时,降低了可用性损耗。
典型使用场景:服务名称,集群配置,持久化服务实例注册、注销
Distro 协议则是 Nacos 自研的 AP 分布式协议,专为海量数据场景设计,核心目标是 “高吞吐、高可用”(AP),通过牺牲强一致性换取最终一致性,适配大规模服务治理需求。
Distro 协议的核心是 “高可用(AP 优先)+ 去中心化部署”,每个节点地位平等,无需 Leader 协调,天然具备高可用特性。
典型场景:临时服务实例注册、注销,应用配置
本文主要分析服务注册过程中相关源码的实现(服务注销过程是类似的),而由于 Nacos 2.x 默认服务实例为「临时实例」,故只分析 Distro 协议服务实例信息同步的实现。
基于 Distro 协议的服务实例信息同步
假设服务 A 向 Nacos 集群节点 1 完成了服务注册,此时 Nacos 集群节点 1 需要往集群节点 2、3 同步服务实例信息
Nacos 集群节点 1 发起同步请求
继续分析 Nacos 服务端服务注册源码,入口为 InstanceRequestHandler#handle(),当将服务实例添加到 publishers 中时,会通过发布 ClientChangedEvent 事件来实现集群节点的同步
处理该事件时会调用 distroProtocol.sync()
将服务信息同步至除自身以外的其它 Nacos 节点
将 targetServer、action 等封装到 DistroDelayTask 中,此时又用到了 NacosDelayTaskExecuteEngine 执行引擎(实际用的是其子类 DistroDelayTaskExecuteEngine)
通过 DistroDelayTaskProcessor 来处理
继续通过 NacosExecuteTaskExecuteEngine 引擎来执行(注意 Delay 改为了 Execute)
“Delay” 就是延迟执行,通过 delay 参数控制延迟时间。最后执行时是通过 “Execute” 来实现的
继续分析 DistroSyncChangeTask 任务执行,其父类的 run() 作为入口
然后再执行 DistroSyncChangeTask#doExecuteWithCallback()
Nacos 集群节点 2 处理同步请求
处理的方法为 DistroDataRequestHandler#handle()
针对 ADD、CHANGE 最终会通过 addServiceInstance() 将新的 instance 添加到 publishers 中,发布 ClientRegisterServiceEvent 事件将 clientId 添加到 publisherIndexes 中
addServiceInstance() 中会再次发布 ClientChangedEvent 事件
针对 DELETE 会从 client 中移除客户端,并发布 ClientDisconnectEvent 事件
发布 ClientChangedEvent、ClientDisconnectEvent 事件的作用,都是将实例信息再次同步给其它 Nacos 集群节点
也就是说服务 A 向 Nacos 集群节点 1 发起服务注册,节点 1 处理完后会将注册信息同步给节点 2、3,节点 2 处理完后,再次将信息同步给节点 1、3(节点 3 亦如此)
这也体现了 Nacos Distro 协议的设计本质:它是一套为「去中心化架构」量身定制的「最终一致性协议」,核心目标是高可用(AP 优先) + 去中心化部署。Distro 协议的同步不是「单向推送」,而是「多节点互相扩散」。
节点 2 的二次同步,本质上是通过多路径冗余同步,解决去中心化架构下的同步失败、数据冲突、故障恢复问题,最终在不牺牲可用性的前提下,保证所有节点的数据最终一致。
如果你觉得这个系列有帮助,欢迎分享给更多需要的伙伴。也欢迎在评论区留言,分享你的心得体会或疑问,我们一起交流,共同进步!也欢迎大家关注我的微信公众号「michael学coding」。