ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Nacos 与 ZooKeeper 注册中心实现对比

Nacos 与 ZooKeeper 注册中心实现对比

本文档对 Jaws 框架中 Nacos 和 ZooKeeper 两种注册中心实现进行全方位比较。

一、底层存储模型

维度NacosZooKeeper
数据模型扁平化服务模型(serviceName + group + instances)树形层级路径模型(类似文件系统)
路径结构jaws/{path}作为 serviceName,group 来自 URL/jaws/{group}/{path}/server/{host:port}多层路径
数据存储URL 参数全部存入 Instance 的metadataMapURL 完整字符串作为 ZK 节点的 data(byte[])
节点类型无区分,instance 只有 ephemeral 属性区分AVAILABLE_SERVERCLIENT两种节点类型

ZK 路径层级(见ZkUtils):

/jaws/{group}/{servicePath}/server/{host:port} ← 服务提供者 /jaws/{group}/{servicePath}/client/{host:port} ← 服务消费者

Nacos 映射(见NacosPathUtils):

serviceName = "jaws/{path}" group = url.getGroup() instance metadata = {protocol, path, ...所有URL参数}

二、服务注册机制

ZooKeeper

  1. 先删后建:注册前先removeNode清除可能残留的旧节点,再createNode
  2. 双节点:父路径为PERSISTENT类型,服务实例节点为EPHEMERAL类型(会话断开自动删除)
  3. 数据载体:节点 data 存储url.toFullStr()完整 URL 字符串

Nacos

  1. 直接注册:调用namingService.registerInstance()即可,无需先清理
  2. 单实体:只注册一个Instance对象,设置ephemeral=true, healthy=true
  3. 数据载体:URL 参数全部放入instance.metadata,额外存储protocolpath

核心区别:ZK 依赖临时节点 + 会话心跳实现自动下线;Nacos 依赖心跳 + 健康检查机制。

三、服务订阅与发现机制

ZooKeeper — CuratorCache 监听

  • 使用CuratorCache监听/server路径下的子节点变化
  • 监听NODE_CREATED/NODE_DELETED事件
  • 事件触发后重新getChildren获取全量子节点列表,逐个getData解析 URL
  • 订阅时还会创建CLIENT临时节点(消费者标记)

Nacos — EventListener 监听

  • 使用namingService.subscribe()注册EventListener
  • 收到NamingEvent后直接从中获取List<Instance>全量实例列表
  • 从 metadata 中还原 protocol/path 构建 URL
  • 不创建额外的消费者节点

核心区别:ZK 是被动通知(只告诉你节点变了,需要自己去拉最新数据);Nacos 是主动推送(直接给你最新实例列表)。

四、断线重连机制

ZooKeeper — 显式重连

ZookeeperRegistry在构造时注册了ConnectionStateListener

if(connectionState==ConnectionState.RECONNECTED){reRegisterServices();// 重新注册所有服务reSubscribeServices();// 重新订阅所有服务}

因为 ZK 临时节点在会话断开后会丢失,重连后必须手动恢复。

Nacos — 无显式重连

NacosRegistry没有连接状态监听。Nacos 客户端 SDK 内部处理了心跳和重连,NamingService会自动维护注册状态。

五、服务发现(doDiscover)

维度NacosZooKeeper
APInamingService.getAllInstances(serviceName, group)curator.getChildren().forPath(parentPath)
数据解析从 metadata 直接构建 URL逐个子节点getData读取 byte[] 再反序列化 URL
容错metadata 无 protocol 时用 refUrl 兜底节点 data 解析失败时用节点名解析 host:port 兜底
路径不存在Nacos SDK 内部处理需先checkExistsgetChildren

六、并发控制

两者结构完全一致:

  • clientLock(ReentrantLock)保护订阅/取消订阅操作
  • serverLock(ReentrantLock)保护注册/注销操作
  • serviceListeners都是HashMap<URL, Map<NotifyListener, 具体监听器>>

七、动态配置对比

维度NacosDynamicConfigurationZookeeperDynamicConfiguration
存储Nacos ConfigService;key→dataId,group 固定为JAWS_CONFIGZK 节点,路径/jaws/dynamic-config/{key}
读写getConfig/publishConfiggetData/setData/create/delete
监听NacosListener回调CuratorCache监听节点变化
连接复用独立创建ConfigService(与注册用 NamingService 不同实例)独立创建CuratorFramework(与注册用客户端不同实例)
删除配置removeConfigcurator.delete()

八、Factory 创建对比

维度NacosRegistryFactoryZookeeperRegistryFactory
客户端NamingFactory.createNamingService(Properties)CuratorFrameworkFactory.builder().build()
重试策略Nacos SDK 内部管理ExponentialBackoffRetry(1000, 3)显式配置
认证username/password 放入 Propertiesdigest模式 ACL 认证
超时CONFIG_LONG_POLL_TIMEOUTsessionTimeoutMs+connectionTimeoutMs分离

九、总结

特性NacosZooKeeper
数据模型扁平,面向服务注册设计通用协调服务
健康检查服务端主动心跳检测会话超时 + 临时节点自动消失
变更通知推送全量实例列表Watch 通知 + 客户端重新拉取
重连恢复SDK 内部处理,应用层无感应用层监听RECONNECTED手动恢复
消费者感知不记录消费者信息创建 CLIENT 临时节点标记消费者
配置中心原生 ConfigService 支持用节点 data 模拟,需自建路径规范
代码复杂度较低(~183行),API 更高级较高(~267行),需手动管理节点生命周期

简而言之:Nacos 实现更简洁,因为 Nacos SDK 封装了更多服务注册的高层语义;ZooKeeper 实现更底层,需要手动处理节点创建/删除、会话重连、消费者标记等细节,但控制粒度也更细。

返回列表