Nacos - 服务注册

Nacos 的服务注册是其核心功能之一。随着版本的演进,Nacos 经历了从 1.x(基于 HTTP)到 2.x(基于 gRPC)的架构升级。

下面我将从客户端发送请求服务端处理请求心跳维持与健康检查三个维度,详细讲解 Nacos(以 2.x 版本为主,兼顾 1.x 区别)的服务注册流程。


一、 整体流程概览

  1. 服务启动:客户端(微服务)启动,读取配置。
  2. 建立连接:客户端与 Nacos 服务端建立长连接(gRPC)。
  3. 发送注册请求:客户端封装实例信息(IP、Port、服务名等)发送给服务端。
  4. 服务端存储:服务端将实例信息存入内存注册表。
  5. 数据同步:服务端将新注册的实例信息同步给集群内的其他 Nacos 节点(Distro 协议)。
  6. 服务变更通知:服务端主动推送最新的服务列表给订阅了该服务的客户端。

二、 详细步骤解析

1. 客户端:发起注册 (Client Side)

  • 入口 :在 Spring Cloud 环境下,注册入口是 NacosServiceRegistry.register() 方法。
  • 封装实例 :构造 Instance 对象,包含:
    • Service Name(服务名)
    • IPPort
    • Weight(权重)
    • Metadata(元数据)
    • Ephemeral(是否是临时实例,默认 true
  • 通信协议
    • Nacos 1.x :通过 HTTP POST 请求发送到 /nacos/v1/ns/instance
    • Nacos 2.x :通过 gRPC 传输。客户端通过 NamingClientProxy 调用 registerService,请求会被封装成 InstanceRequest 发送。

2. 服务端:接收与存储 (Server Side)

当 Nacos 服务端收到注册请求后,会执行以下逻辑:

  • 解析请求InstanceRequestHandler 接收 gRPC 请求(1.x 是 InstanceController)。
  • 内存注册表维护
    • Nacos 内部维护了一个多层的 Map 结构: Map<namespace, Map<group::serviceName, Service>>
    • Service 类中包含多个 Cluster(集群)。
    • Cluster 中维护了两个 Set<Instance>:一个是 临时实例 ,一个是 持久化实例
  • 写时复制 (CopyOnWrite) :为了防止高并发下的读写冲突,Nacos 在更新实例列表时采用了类似 CopyOnWrite 的机制。它会先读取旧的列表,创建一个新列表,把新实例放进去,最后替换旧列表。

3. 服务端:一致性协议 (Consistency)

Nacos 根据实例类型(临时/持久化)走不同的协议:

  • 临时实例(默认,AP模式)
    • 使用 Distro 协议(Nacos 自研)。
    • 注册节点会立即同步给集群内其他节点。
    • 遵循 最终一致性,保证高可用。
  • 持久化实例(CP模式)
    • 使用 Raft 协议(JRaft 实现)。
    • 必须过半数节点写入成功才算注册成功。
    • 保证 强一致性

4. 服务端:推送通知 (Push)

  • 一旦注册表发生变化,服务端会触发 ServiceChangeEvent
  • 推送机制 :服务端通过 PushService 找到所有订阅了该服务的客户端,通过 gRPC(2.x)或 UDP(1.x)将最新的实例列表推送过去。
  • 客户端缓存 :客户端收到更新后,会更新本地的 ServiceInfo 缓存,从而实现负载均衡时拿到最新的地址。

三、 核心:健康检查机制

注册流程完成后,如何保证服务一直"在线"?

  1. Nacos 1.x (HTTP + 心跳)

    • 客户端每隔 5秒 发送一次心跳(Beat)。
    • 服务端若 15秒 没收到心跳,标记为不健康。
    • 30秒 没收到心跳,直接剔除实例。
  2. Nacos 2.x (gRPC + 连接探测)

    • 长连接 :基于 gRPC 的 Stream。如果客户端宕机,gRPC 连接会断开。
    • 连接断开即剔除:服务端监控连接状态,一旦连接异常断开(Connection Disconnect),服务端会立即触发下线流程(针对临时实例)。这种方式比心跳更实时。

四、 总结:1.x 与 2.x 的关键区别

特性 Nacos 1.x Nacos 2.x
通信协议 HTTP gRPC (双向流)
注册效率 每次注册/心跳都是短连接,开销大 长连接复用,极大减少连接握手消耗
实时性 依赖心跳间隔,响应稍慢 连接断开瞬时感应,响应极快
一致性协议 Distro (AP) / Raft (CP) 优化后的 Distro / JRaft

总结口述版

"Nacos 注册流程首先是客户端通过 gRPC(2.x)向服务端发起注册请求。服务端接收后,会将实例信息存入内存中的双层 Map 结构中,并根据实例是否是临时的,选择走 Distro 异步同步(AP)或 Raft 强一致同步(CP)。存储完成后,服务端会发布变更事件,通过长连接异步推送给所有订阅该服务的客户端。最后,通过 gRPC 的长连接状态来维持实例的健康状态,一旦断开则自动剔除。"

相关推荐
brahmsjiang1 分钟前
Java类加载机制解析:从JVM启动到双亲委派,再到Android的特殊实现
android·java·jvm
yaaakaaang3 分钟前
十一、享元模式
java·享元模式
卓怡学长5 分钟前
基于 SpringBoot 的生活信息分享平台,从 0 到 1 完整实现(附源码 + 数据库)
java·数据库·spring boot·tomcat·maven
ID_180079054736 分钟前
Python解析小红书(XHS)笔记评论 API,json数据返回参考
java·服务器·数据库
努力努力再努力wz7 分钟前
【C++高阶系列】告别内查找局限:基于磁盘 I/O 视角的 B 树深度剖析与 C++ 泛型实现!(附B树实现源码)
java·linux·开发语言·数据结构·c++·b树·算法
hero.fei9 分钟前
RoaringBitmap在SpringBoot中的使用以及与BitSet对比
java·spring boot·spring
Traving Yu10 分钟前
Spring源码与框架原理
java·后端·spring
Lyyaoo.15 分钟前
【JAVA基础面经】线程安全的单例模式
java·安全·单例模式
_李小白20 分钟前
【OSG学习笔记】Day 39: NodeCallback(帧回调机制)
java·笔记·学习
如来神掌十八式22 分钟前
设计模式之装饰器模式
java·设计模式