Nacos 与 Eureka、ZooKeeper 的区别?

#Java#面试八股

Nacos 与 Eureka、ZooKeeper 的区别?

结论先行:三者都能做注册中心,但定位不同。Eureka 是纯 AP 的注册中心,靠客户端缓存与自我保护保证可用性;ZooKeeper 是 CP 的分布式协调器,用 ZAB 保证强一致,注册中心只是它的副业;Nacos 同时支持 AP 与 CP(临时实例走 Distro/AP,持久实例走 Raft/CP),并且注册中心 + 配置中心二合一。

1. CAP 定位

        一致性 C
           ▲
   ZK ●    │    ● Nacos(持久实例,CP 模式)
           │
───────────┼───────────▶ 可用性 A
           │
      Eureka ●   ● Nacos(临时实例,AP 模式,默认)
组件一致性协议CAP注册中心语义
Eureka节点间异步复制(peer to peer)AP允许短暂不一致,优先可用
ZooKeeperZAB(Leader 写,过半确认)CP选举期间不可写,注册中心不可用
Nacos(临时实例)Distro(自研 AP 协议)AP心跳保活,异步同步
Nacos(持久实例)Raft(JRaft)CP强一致,适合 DNS/数据库类服务

2. 关键能力对比

维度EurekaZooKeeperNacos
健康检查客户端心跳续约(30s)会话 + 临时节点心跳(5s)+ 主动探测
服务发现客户端拉取 + 本地缓存Watch 推送拉取 + 推送(2.x 走 gRPC 长连接)
配置中心无可用 znode 但难用内置,支持动态刷新
权重/灰度无无支持权重、元数据、分组
命名空间隔离无靠 pathnamespace/group 两级
自我保护有(15 分钟续约率 <85% 停止剔除)无有健康保护阈值
控制台简单无(需第三方)完善
Spring Cloud 集成Netflix 体系(已停更)需第三方官方 Alibaba 体系

3. 为什么 ZooKeeper 不适合做注册中心

ZooKeeper 的强一致带来一个副作用:Leader 选举期间整个集群不可写。注册中心最怕这个——服务实例恰好在这段时间上下线,注册/续约全部失败,调用方可能拿到过期列表。

另外,ZK 的 Watch 是一次性的,客户端要反复注册;会话超时(默认 30s 级)与网络抖动叠加时容易误剔除实例。Eureka 的自我保护正是为这类场景设计的:宁可保留不健康实例,也不要把健康实例全剔掉。

4. 配置示例

spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: prod            # 环境隔离
        group: TRADE               # 业务分组
        cluster-name: SH           # 同机房优先
        ephemeral: true            # true=临时实例(AP),false=持久实例(CP)
        weight: 1.0
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: prod
        group: TRADE

Eureka 的等价配置(仅作对比):

eureka:
  client:
    service-url:
      defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/
    registry-fetch-interval-seconds: 30
  instance:
    lease-renewal-interval-in-seconds: 30
    lease-expiration-duration-in-seconds: 90

5. 选型建议

场景建议
新项目、Spring Cloud AlibabaNacos(注册 + 配置一体)
已有 Eureka 集群、稳定运行不必急着迁移,但要知道它已停更
需要强一致的元数据协调(选主、分布式锁)ZooKeeper,而不是拿它做注册中心
多语言、K8s 环境Nacos 或 Consul / K8s Service

6. 常见追问

追问一:Eureka 的自我保护是什么? 如果 15 分钟内续约失败的比例低于 85%,Eureka 认为「大面积失联更可能是网络问题而非实例宕机」,于是停止剔除任何实例。好处是避免误杀,坏处是调用方可能拿到已死的实例,必须靠客户端重试兜底。

追问二:Nacos 的 AP 和 CP 怎么切? 按实例类型切:ephemeral=true 的临时实例走 Distro(AP),ephemeral=false 的持久实例走 Raft(CP)。同一个服务内不建议混用。

追问三:Nacos 挂了,服务还能调用吗? 能,短期内可以。客户端会缓存服务列表快照到本地文件,注册中心不可用时用快照继续调用;但新实例上下线感知不到,配置也无法更新。

追问四:ZK 的临时节点不是天然适合注册吗? 临时节点确实能表达「会话存活」,但它的 CP 语义与注册中心的高可用诉求冲突,且没有权重、元数据、配置管理等注册中心必备能力,所以只能算「能用」,不算「好用」。

追问五:Consul 和它们比呢? Consul 用 Raft(CP)+ Gossip,支持多数据中心和健康检查,跨语言好;但写入受 Leader 限制,且 Spring Cloud 集成度不如 Nacos 在国内普及。

小结

三者的本质区别是一致性取舍与职责范围:Eureka 用 AP 换可用,ZK 用 CP 换强一致但把注册中心当副业,Nacos 用「按实例类型切换 AP/CP」同时覆盖两类诉求,并把配置中心纳入进来。选型时先问「注册中心能不能短时间不可用」,答案决定了 CAP 方向。

笔记加载中…