Nacos 服务实例注册的流程是怎样的?服务端如何处理注册请求?

在这里插入图片描述
Nacos 的服务注册是指一个服务实例(比如一个微服务的某个副本)启动后,将自身的网络信息(IP、端口、服务名、元数据等)告知 Nacos Server,以便其他服务能够发现并调用它。

整体流程概览:

  1. 客户端(服务实例): 应用启动,初始化 Nacos Client SDK。
  2. 客户端: SDK 收集实例信息(IP、端口、服务名、集群、健康状态、元数据、是否临时节点等)。
  3. 客户端: SDK 向 Nacos Server 发送 HTTP 注册请求。
  4. 服务端: Nacos Server 接收到注册请求。
  5. 服务端: 解析请求参数,进行校验。
  6. 服务端: 根据服务名、分组、命名空间查找或创建对应的 Service 对象。
  7. 服务端:Service 对象中添加或更新该 Instance(实例)信息。
  8. 服务端 (集群模式): 将实例信息同步到集群中的其他 Nacos 节点(根据 AP 或 CP 模式采用不同策略)。
  9. 服务端: 将更新后的服务信息推送给订阅了该服务的客户端(服务发现)。
  10. 服务端: 向发起注册请求的客户端返回响应(成功或失败)。
  11. 客户端 (临时实例): 注册成功后,启动心跳任务,定期向 Nacos Server 发送心跳以维持注册状态。

客户端(Nacos Client SDK)注册流程详解:

  1. 依赖引入与配置:

    • 通常在项目中(如 Spring Cloud 应用)引入 spring-cloud-starter-alibaba-nacos-discovery 依赖。
    • 在配置文件 (application.ymlapplication.properties) 中配置 Nacos Server 地址 (spring.cloud.nacos.discovery.server-addr)、服务名 (spring.application.name)、命名空间 (namespace)、分组 (group)、集群名 (cluster-name)、实例 IP (ip)、端口 (port)、元数据 (metadata)、是否临时实例 (ephemeral, 默认为 true) 等。SDK 会自动读取这些配置。
  2. 初始化:

    • 应用启动时,Spring Cloud Alibaba Nacos Discovery 自动配置会初始化 NacosServiceRegistryNamingService (Nacos Client SDK 的核心类)。
  3. 触发注册:

    • 通常在 Spring Boot 应用的 ApplicationReadyEvent 事件触发后,或者通过其他生命周期回调,NacosServiceRegistryregister() 方法会被调用。
  4. 构建注册信息 (Instance):

    • SDK 根据配置和运行时信息(如自动获取的 IP、端口)创建一个 Instance 对象。关键属性包括:
      • serviceName: 服务名
      • ip: 实例 IP 地址
      • port: 实例端口
      • clusterName: 集群名称 (默认为 “DEFAULT”)
      • namespaceId: 命名空间 ID (默认为 “public”)
      • groupName: 分组名称 (默认为 “DEFAULT_GROUP”)
      • weight: 权重 (用于负载均衡,默认为 1.0)
      • metadata: 元数据 (Key-Value 对,用于传递自定义信息)
      • ephemeral: 是否为临时实例 (非常重要!)
        • true (默认): 临时实例。需要客户端主动发送心跳维持,如果 Nacos Server 一段时间没收到心跳,会自动剔除该实例。适用于绝大多数动态伸缩的微服务。
        • false: 持久化实例。注册后除非手动调用反注册 API,否则不会被 Nacos Server 主动剔除。通常用于注册一些状态相对固定的服务或组件。
      • enabled: 是否启用 (是否接收流量,默认为 true)
      • healthy: 健康状态 (默认为 true)
  5. 发送注册请求:

    • NamingService 调用其 registerInstance 方法。
    • SDK 内部会选择一个 Nacos Server 节点(根据负载均衡策略),然后构造一个 HTTP PUT 请求发送到 Nacos Server 的 /nacos/v1/ns/instance 接口。
    • 请求参数通常放在 URL Query String 中,包含上述 Instance 对象的所有信息。
  6. 处理响应与后续:

    • 客户端等待 Nacos Server 的响应。如果成功(通常返回 “ok” 或 HTTP 200),则注册完成。
    • 如果注册的是临时实例 (ephemeral=true),SDK 会立即启动一个后台心跳线程(BeatReactor),默认每隔 5 秒向 Nacos Server 发送一次心跳(HTTP PUT 请求到 /nacos/v1/ns/instance/beat)。

服务端(Nacos Server)处理注册请求详解:

  1. 接收请求:

    • Nacos Server 的 Web 容器(如 Tomcat/Jetty)接收到来自客户端的 HTTP PUT 请求 (/nacos/v1/ns/instance)。
    • 请求被路由到 InstanceControllerregister 方法(或类似处理逻辑)。
  2. 参数解析与校验:

    • 从请求中提取 serviceName, ip, port, namespaceId, groupName, clusterName, ephemeral 等所有参数。
    • 进行必要的参数校验,例如 serviceName, ip, port 是否为空,端口是否合法等。
  3. 获取或创建 Service:

    • Nacos Server 内部维护着服务注册信息,通常使用一个多层 Map 结构来存储:Namespace -> Group -> ServiceName -> Service
    • 服务端根据请求中的 namespaceId, groupName, serviceName 在内存中的 ServiceManager 里查找对应的 Service 对象。
    • 如果 Service 对象不存在,则创建一个新的 Service 对象,并设置其相关属性(如服务名、分组、保护阈值等)。
  4. 处理 Instance (核心逻辑):

    • 获取到(或创建了)Service 对象后,开始处理具体的 Instance
    • Nacos Server 会根据 ipport (以及 clusterName) 来唯一标识一个实例。
    • 检查实例是否存在:Service 对象的实例列表 (instances) 中查找是否已存在具有相同 ip:port:clusterName 的实例。
    • 更新实例: 如果实例已存在:
      • 更新该实例的元数据 (metadata)、权重 (weight)、enabled 状态等信息。
      • 特别地: 更新该实例的最后心跳时间 (lastBeatTimestamp) 为当前时间。这使得注册操作本身也具有心跳的效果,并且是幂等的。重复注册同一个实例相当于一次心跳 + 信息更新。
    • 添加新实例: 如果实例不存在:
      • 根据请求参数创建一个新的 Instance 对象。
      • 设置其初始健康状态、启用状态、最后心跳时间等。
      • 将这个新的 Instance 对象添加到 Service 的实例列表中。
      • 如果是该 Service 的第一个实例,可能还会触发一些初始化逻辑。
  5. 区分临时与持久化实例:

    • 临时实例 (ephemeral=true):
      • Nacos Server 依赖客户端的心跳来判断其存活。服务端会有一个定时任务(ClientBeatCheckTask)定期检查所有临时实例的 lastBeatTimestamp,如果 当前时间 - lastBeatTimestamp 超过了阈值(默认 15 秒没心跳认为不健康,30 秒没心跳直接剔除),则会将实例标记为不健康或直接从列表中移除。
      • 临时实例的注册、注销、状态变更通常使用 Nacos 自研的 Distro 协议(一种优化的 Gossip 协议,AP 模型)在 Nacos Server 集群节点间进行异步数据同步。这保证了高可用和高性能,但牺牲了短暂的数据一致性。
    • 持久化实例 (ephemeral=false):
      • Nacos Server 不会因为收不到心跳而移除它们。它们的状态变更(注册、注销)需要显式调用 API。
      • 持久化实例的数据一致性通常可以通过 Raft 协议(CP 模型)来保证。当处理持久化实例的注册/注销请求时,请求会被转发给 Raft Leader,通过 Raft Log 复制和状态机应用来确保集群中所有节点数据强一致。
  6. 数据同步 (集群模式):

    • AP 模式 (Distro协议 - 主要用于临时实例): 接收到注册请求的节点处理完本地内存后,会将这个实例变更信息(添加或更新)通过 Distro 协议异步发送给集群中的其他节点。其他节点收到同步任务后更新自己的内存数据。
    • CP 模式 (Raft协议 - 主要用于持久化实例): 如果是持久化实例,请求可能需要转发给 Raft Leader,Leader 通过 Raft 协议将变更提交,只有当大部分节点确认提交后,Leader 才完成操作并向客户端返回成功。
  7. 触发事件与推送:

    • 当一个 Service 的实例列表发生变化(添加、移除、更新)时,Nacos Server 会发布一个内部事件 (ServiceChangeEvent)。
    • PushService (推送服务) 监听这些事件。如果发现有客户端(通常是服务消费者)通过长连接 (gRPC) 或 UDP 推送机制订阅了这个 ServicePushService 会将最新的实例列表信息主动推送给这些订阅者。这使得服务发现更加及时。
  8. 返回响应:

    • 服务端处理完成后(对于 AP 模式,本地处理完成即可;对于 CP 模式,Raft 提交成功后),向发起注册请求的客户端返回 HTTP 响应,通常是一个简单的 “ok” 字符串或 JSON 对象表示成功。

总结关键点:

  • 注册本质: 客户端向服务端发送包含自身信息的 HTTP PUT 请求。
  • 核心数据结构: 服务端内存中维护 Namespace -> Group -> ServiceName -> Service -> List<Instance> 的结构。
  • 幂等性: 注册操作是幂等的,重复注册同一实例等于更新信息 + 续约(心跳)。
  • 临时 vs 持久: ephemeral 参数决定实例类型,影响心跳机制和数据同步协议(AP vs CP)。
  • 心跳: 临时实例需要客户端定期发送心跳维持注册。
  • 集群同步: AP 模式(Distro)用于临时实例,保证最终一致性和高可用;CP 模式(Raft)可用于持久化实例,保证强一致性。
  • 主动推送: 服务端会在实例变更后主动将新列表推送给订阅者。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值