面试知识库
高 进阶

Nacos注册中心原理#

一句话答案#

Nacos 临时实例走 AP(Distro 协议),1.x 靠客户端 HTTP 心跳续约、2.x 起靠 gRPC 长连接判断存活;持久实例走 CP(JRaft),由服务端主动探测健康;同时支持配置管理。

核心要点

维度NacosEurekaZooKeeper
CAP 模型AP + CP(可切换)APCP
一致性协议Distro(AP)/ JRaft(CP)无,各节点平等,对等复制ZAB 协议(类 Paxos)
健康检查临时实例:1.x 客户端心跳(5s)/ 2.x gRPC 长连接存活;持久实例:服务端主动探测客户端心跳(默认 30s)Session + 临时节点
推/拉模型1.x:UDP 推送 + 客户端定时拉取;2.x 起:gRPC 长连接推送 + 定时对账拉(默认 30s 轮询)推(Watch 机制)
自我保护无 Eureka 式自我保护,用保护阈值替代(见下行)有(Renew 比例 < 85% 进入保护模式,不剔除实例)无(过半节点不可用则不可写)
雪崩保护支持(保护阈值 protectThreshold:健康实例比例低于阈值时返回全部实例,含不健康的)支持(自我保护模式)不支持(CP 模式下可能拒绝服务)
配置中心内置(Nacos Config)不支持(需搭配 Spring Cloud Config)可实现但需自行封装
多数据中心支持(Group、Namespace)支持(Region/Zone)需要 Observer 模式
权重/灰度支持(原生权重、元数据路由)不支持(需自行扩展)不支持
访问控制支持(Namespace 级别隔离)不支持ACL
社区维护阿里巴巴活跃维护(3.x 已发布)当年的 Eureka 2.0 重写计划 2018 年终止;1.x 线后续以社区维护为主,仍在发版(现 2.0.x 为 Jakarta 版)Apache 活跃但偏底层

选型建议:

  • Nacos:首选方案。AP/CP 可切换,同时提供配置中心,功能最全面,Spring Cloud Alibaba 生态深度集成
  • Eureka:仅需 AP 模型且团队有历史积累时可用;仍在维护、Spring Cloud Netflix 继续支持,但只做维护性更新,功能基本不再演进
  • ZooKeeper:Dubbo 早期最常用的注册中心(现在 Dubbo 也常配 Nacos),但 CP 模型在网络分区时可能拒绝服务,不适合大规模微服务注册

面试要点:

  • 注册中心应优先选择 AP 模型:网络分区时,宁可返回旧数据(某些实例可能已下线),也不要拒绝服务(CP 模型在分区时可能不可用)
  • ZK 的 CP 特性对注册中心来说反而是劣势——分区时无法写入会导致服务注册失败

面试回答(2分钟版)

Nacos 是 Spring Cloud Alibaba 生态的核心组件,同时提供注册中心和配置中心能力。作为注册中心,Nacos 的最大特点是支持 AP 和 CP 两种模式切换:临时实例走 AP 模式使用 Distro 协议,优先保证可用性,1.x 客户端通过心跳维持注册,2.x 起改为 gRPC 长连接、连接断开即注销;持久实例走 CP 模式使用 JRaft 协议,优先保证一致性。健康检查方面 Nacos 同时支持客户端心跳和服务端主动探测,比 Eureka 只有客户端心跳更可靠。服务变更通知 1.x 是 UDP 推送加客户端定时拉取,2.x 起改为 gRPC 长连接推送,比 Eureka 默认 30 秒轮询实时性更好。和其他注册中心对比:Eureka 纯 AP、仍在维护但基本不再演进;ZooKeeper 纯 CP,网络分区时可能拒绝服务,对注册中心来说反而是劣势。注册中心应优先选 AP 模型,因为返回旧数据总比拒绝服务好。另外 Nacos 挂了也不影响短期服务调用,客户端有本地缓存兜底。

追问与易错

追问方向:

  • “心跳检测和 Eureka 区别?”→ Nacos 支持临时实例(1.x 客户端心跳:5s 发一次、15s 未收到标记不健康、30s 删除,类似 Eureka;2.x 起靠 gRPC 长连接存活判断)和永久实例(服务端主动探测 TCP/HTTP/MySQL);Eureka 只有客户端心跳且有自我保护机制(大面积心跳丢失时不剔除),Nacos 的健康检查更灵活
  • “集群怎么部署?”→ 至少 3 个节点组成集群,通过 cluster.conf 配置节点列表;临时实例一直用 Distro 协议(AP),永久实例用 Raft(CP,1.4.0 起从自研 Raft 换成 JRaft),配置数据生产环境存外置 MySQL;2.x 起客户端与服务端改用 gRPC 长连接(主端口 8848 + 偏移 1000 的 9848,集群间 9849,JRaft 7848);3.x 起最低 JDK 17、控制台独立到 8080 端口、默认开启鉴权
  • “实例下线但心跳还在?”→ 可能是优雅停机没做好,应用关闭前应主动调用 deregister 注销实例;或者用 Spring Cloud 的 shutdown endpoint 配合 @PreDestroy 钩子主动下线,避免流量打到已关闭的实例

易错点:

  • ❌ Nacos 挂了服务不能调——客户端有本地缓存
  • ❌ Nacos 2.x 临时实例还是靠 5 秒 HTTP 心跳续约——2.x gRPC 客户端靠长连接存活判断,连接断开实例即被移除;只有 1.x 客户端或 HTTP OpenAPI 注册才走心跳
  • ❌ 升级 Nacos 2.x 只开放 8848 端口就够——客户端 gRPC 走 8848+1000=9848,不放行会连不上