面试记录 2026-09-27
题目:Nacos的服务注册和服务发现的过程是怎么样的?
难度:medium
标签:spring/cloud, general/knowledge
评分:⭐☆☆☆☆(1/5)
我的回答
Nacos 的服务注册,加载类。发送请求信息,确定建立关系。进行注册,翻译过程是在。通过请求对应的端口接口实现发现,上线之后启动的时候进行调用,实现发现。然后双方建立互通消息,完成注册。
点评
优点:
- 隐约说到了"启动时注册""请求接口发现",方向对但表述极度不清晰
不足:
- 完全没有讲具体的 HTTP/gRPC 请求流程:注册是 PUT/POST
/nacos/v1/ns/instance,发现是 GET /nacos/v1/ns/instance/list
- 完全没有讲心跳续约机制:客户端每 5 秒向 Nacos 发心跳(1.x),Nacos 判 15 秒不健康、30 秒剔除。这是服务注册最核心的机制
- 完全没有讲服务端集群的通信:Nacos 集群内节点通过 Distro(AP)或 Raft(CP)协议同步数据
- 完全没有讲客户端缓存和监听机制:客户端本地缓存服务列表、通过长轮询(1.x)或 gRPC 长连接(2.x)监听变化
- 完全没讲健康检查流程:Nacos 主动 health check、临时实例心跳模式、永久实例 TCP check
- "翻译过程是在"、"双方建立互通消息" 这种表述说明对机制理解不深
补充(完整流程):
服务注册:
- 服务启动,读取
spring.cloud.nacos.discovery.server-addr 等配置
- 通过
NamingService.registerInstance() 调用 HTTP PUT /nacos/v1/ns/instance(或 2.x gRPC)向 Nacos 上报实例元数据(IP、端口、权重、健康状态、metadata)
- Nacos 集群接收请求,通过 Distro 协议把实例信息异步同步到其他节点(临时实例)
- 客户端启动定时任务,每 5 秒发一次心跳(
/nacos/v1/ns/instance/beat)
- Nacos 服务端判断:15 秒无心跳标记不健康,30 秒无心跳自动剔除
- 服务优雅关闭时主动调用
DeregisterInstance 接口
服务发现:
- 消费端启动时通过
NamingService.getInstances() 或 subscribe() 请求服务列表
- HTTP GET
/nacos/v1/ns/instance/list?serviceName=xxx 获取所有健康实例
- 客户端本地缓存服务列表,避免每次调用都查 Nacos
- 监听机制:1.x 用长轮询(30 秒挂起等待变化),2.x 用 gRPC 长连接主动 push
- 服务列表变化时更新本地缓存,消费端通过负载均衡(轮询/随机/权重)选实例发起调用
关键细节:
- 临时实例(默认):AP(Distro),靠心跳续约,故障自动剔除
- 永久实例:CP(Raft),靠持久化,不自动剔除
- 健康检查模式:临时实例 = 客户端心跳(推),永久实例 = 服务端主动(拉)
- 集群内通信:Distro 协议做数据最终一致,Raft 做配置一致性
完整讲解
第一部分:知识重点剖析
核心考点定位:考察对 Nacos 客户端与集群两端交互全流程的深入理解,尤其是心跳续约和健康检查机制。
知识点拆解:
- 服务注册流程:服务启动 → 上报实例(IP/port/权重/metadata)→ Nacos 集群同步(Distro/Raft)→ 客户端心跳续约(5s/次,15s 判不健康,30s 剔除)→ 优雅关闭时主动反注册。
- 服务发现流程:消费端启动 → 拉取服务列表并本地缓存 → 建立监听(长轮询或 gRPC push)→ 变化时更新缓存 → 负载均衡选实例发起调用。
- 心跳 vs 健康检查:临时实例走客户端推(心跳),永久实例走服务端拉(TCP check)。
- 集群内同步:
- Distro:临时实例用,AP 一致性,异步复制,容错好
- Raft/JRaft:永久实例用,CP 一致性,强一致,性能稍低
- 配置监听:1.x 长轮询(30s 挂起),2.x gRPC 长连接(推送更快、开销更小)
- 本地缓存:客户端缓存 Nacos 数据(文件缓存),Nacos 集群挂了仍能读到最近一次的服务列表,实现降级。
递进:注册是"上报+心跳续约",发现是"拉取+监听+本地缓存"。Nacos 用双一致性模型支撑两类实例。
第二部分:考察方向与延伸递进
考察方向:
- 深度:心跳机制的三级判定(healthy → suspicious → un-healthy)、Distro 协议如何保证 AP 一致
- 广度:Eureka 的自我保护、Zookeeper 的 Watch 机制、Consul 的健康检查方式对比
- 应用:生产环境 Nacos 集群挂了怎么办、如何优雅下线、如何排查服务列表不更新
延伸递进面试题:
- 临时实例和永久实例有什么区别?心跳机制为什么重要?
- 解答要点:临时实例用 Distro(AP)+ 心跳续约,节点挂掉自动摘除,适合无状态服务;永久实例用 Raft(CP)+ 服务端主动 check,不自动剔除,适合数据库等有状态节点。心跳是临时实例存活的证明。
- Nacos 集群挂了,服务还能继续通信吗?
- 解答要点:可以,客户端本地有缓存,服务列表最近一次的快照能读;已建立的连接不受影响;只是新的实例变化感知不到,健康状态也不会更新。所以生产 Nacos 至少 3 节点。
- Nacos 1.x 和 2.x 的服务发现机制有什么区别?
- 解答要点:1.x 用 HTTP 长轮询(30s),2.x 用 gRPC 长连接推送,性能提升 10 倍;2.x 支持 Raft 强一致,1.x 只支持 Distro;2.x 端口多 9848/9849 两个 gRPC 端口。
- Nacos 服务发现的推送机制和 Eureka 的自我保护有什么区别?
- 解答要点:Nacos 是实时推送,客户端本地缓存;Eureka 是客户端主动拉取 + 自我保护(30 秒内 15% 掉线不摘除,防止网络抖动误杀)。Eureka 只适合短连接 + 客户端拉取场景。
第三部分:面试者参考回答(300-600 字口语化)
面试官您好,Nacos 的服务注册和发现是两个方向相反的交互流程,我分开讲。
服务注册分 4 步:
- 启动上报:服务启动时通过 SDK 调
NamingService.registerInstance(),底层是 HTTP PUT /nacos/v1/ns/instance(2.x 是 gRPC),把自身 IP、端口、权重、metadata 上报给 Nacos;
- 集群同步:Nacos 接收后,临时实例走 Distro 协议把数据异步复制到集群其他节点(AP 最终一致),永久实例走 Raft(CP 强一致);
- 心跳续约:客户端每 5 秒发一次心跳
/nacos/v1/ns/instance/beat;Nacos 判 15 秒没心跳标记为不健康、30 秒还没心跳就自动剔除;
- 优雅下线:服务关闭时调
DeregisterInstance 接口主动反注册,避免被误杀。
服务发现分 3 步:
- 首次拉取:消费端启动时调
getInstances() 或 subscribe(),HTTP GET /nacos/v1/ns/instance/list?serviceName=xxx 拿到全部健康实例,本地缓存这份列表;
- 监听变化:1.x 用长轮询(30 秒挂起连接,有变化立即返回),2.x 用 gRPC 长连接(服务端 push);有实例上下线时立即更新本地缓存;
- 负载均衡调用:消费端从本地缓存里按轮询/随机/权重/一致性哈希选实例发起实际调用。
两个关键点:
- 客户端本地缓存很重要:Nacos 集群挂了,客户端还能读缓存,服务发现降级不断;
- 临时/永久实例区别:临时走 AP + 心跳续约,永久走 CP + 服务端主动 check。