
Nacos 的服务注册是指一个服务实例(比如一个微服务的某个副本)启动后,将自身的网络信息(IP、端口、服务名、元数据等)告知 Nacos Server,以便其他服务能够发现并调用它。
整体流程概览:
- 客户端(服务实例): 应用启动,初始化 Nacos Client SDK。
- 客户端: SDK 收集实例信息(IP、端口、服务名、集群、健康状态、元数据、是否临时节点等)。
- 客户端: SDK 向 Nacos Server 发送 HTTP 注册请求。
- 服务端: Nacos Server 接收到注册请求。
- 服务端: 解析请求参数,进行校验。
- 服务端: 根据服务名、分组、命名空间查找或创建对应的
Service对象。 - 服务端: 在
Service对象中添加或更新该Instance(实例)信息。 - 服务端 (集群模式): 将实例信息同步到集群中的其他 Nacos 节点(根据 AP 或 CP 模式采用不同策略)。
- 服务端: 将更新后的服务信息推送给订阅了该服务的客户端(服务发现)。
- 服务端: 向发起注册请求的客户端返回响应(成功或失败)。
- 客户端 (临时实例): 注册成功后,启动心跳任务,定期向 Nacos Server 发送心跳以维持注册状态。
客户端(Nacos Client SDK)注册流程详解:
-
依赖引入与配置:
- 通常在项目中(如 Spring Cloud 应用)引入
spring-cloud-starter-alibaba-nacos-discovery依赖。 - 在配置文件 (
application.yml或application.properties) 中配置 Nacos Server 地址 (spring.cloud.nacos.discovery.server-addr)、服务名 (spring.application.name)、命名空间 (namespace)、分组 (group)、集群名 (cluster-name)、实例 IP (ip)、端口 (port)、元数据 (metadata)、是否临时实例 (ephemeral, 默认为true) 等。SDK 会自动读取这些配置。
- 通常在项目中(如 Spring Cloud 应用)引入
-
初始化:
- 应用启动时,Spring Cloud Alibaba Nacos Discovery 自动配置会初始化
NacosServiceRegistry和NamingService(Nacos Client SDK 的核心类)。
- 应用启动时,Spring Cloud Alibaba Nacos Discovery 自动配置会初始化
-
触发注册:
- 通常在 Spring Boot 应用的
ApplicationReadyEvent事件触发后,或者通过其他生命周期回调,NacosServiceRegistry的register()方法会被调用。
- 通常在 Spring Boot 应用的
-
构建注册信息 (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)
- SDK 根据配置和运行时信息(如自动获取的 IP、端口)创建一个
-
发送注册请求:
NamingService调用其registerInstance方法。- SDK 内部会选择一个 Nacos Server 节点(根据负载均衡策略),然后构造一个 HTTP PUT 请求发送到 Nacos Server 的
/nacos/v1/ns/instance接口。 - 请求参数通常放在 URL Query String 中,包含上述
Instance对象的所有信息。
-
处理响应与后续:
- 客户端等待 Nacos Server 的响应。如果成功(通常返回 “ok” 或 HTTP 200),则注册完成。
- 如果注册的是临时实例 (
ephemeral=true),SDK 会立即启动一个后台心跳线程(BeatReactor),默认每隔 5 秒向 Nacos Server 发送一次心跳(HTTP PUT 请求到/nacos/v1/ns/instance/beat)。
服务端(Nacos Server)处理注册请求详解:
-
接收请求:
- Nacos Server 的 Web 容器(如 Tomcat/Jetty)接收到来自客户端的 HTTP PUT 请求 (
/nacos/v1/ns/instance)。 - 请求被路由到
InstanceController的register方法(或类似处理逻辑)。
- Nacos Server 的 Web 容器(如 Tomcat/Jetty)接收到来自客户端的 HTTP PUT 请求 (
-
参数解析与校验:
- 从请求中提取
serviceName,ip,port,namespaceId,groupName,clusterName,ephemeral等所有参数。 - 进行必要的参数校验,例如
serviceName,ip,port是否为空,端口是否合法等。
- 从请求中提取
-
获取或创建 Service:
- Nacos Server 内部维护着服务注册信息,通常使用一个多层 Map 结构来存储:
Namespace -> Group -> ServiceName -> Service。 - 服务端根据请求中的
namespaceId,groupName,serviceName在内存中的ServiceManager里查找对应的Service对象。 - 如果
Service对象不存在,则创建一个新的Service对象,并设置其相关属性(如服务名、分组、保护阈值等)。
- Nacos Server 内部维护着服务注册信息,通常使用一个多层 Map 结构来存储:
-
处理 Instance (核心逻辑):
- 获取到(或创建了)
Service对象后,开始处理具体的Instance。 - Nacos Server 会根据
ip和port(以及clusterName) 来唯一标识一个实例。 - 检查实例是否存在: 在
Service对象的实例列表 (instances) 中查找是否已存在具有相同ip:port:clusterName的实例。 - 更新实例: 如果实例已存在:
- 更新该实例的元数据 (
metadata)、权重 (weight)、enabled状态等信息。 - 特别地: 更新该实例的最后心跳时间 (
lastBeatTimestamp) 为当前时间。这使得注册操作本身也具有心跳的效果,并且是幂等的。重复注册同一个实例相当于一次心跳 + 信息更新。
- 更新该实例的元数据 (
- 添加新实例: 如果实例不存在:
- 根据请求参数创建一个新的
Instance对象。 - 设置其初始健康状态、启用状态、最后心跳时间等。
- 将这个新的
Instance对象添加到Service的实例列表中。 - 如果是该 Service 的第一个实例,可能还会触发一些初始化逻辑。
- 根据请求参数创建一个新的
- 获取到(或创建了)
-
区分临时与持久化实例:
- 临时实例 (
ephemeral=true):- Nacos Server 依赖客户端的心跳来判断其存活。服务端会有一个定时任务(
ClientBeatCheckTask)定期检查所有临时实例的lastBeatTimestamp,如果当前时间 - lastBeatTimestamp超过了阈值(默认 15 秒没心跳认为不健康,30 秒没心跳直接剔除),则会将实例标记为不健康或直接从列表中移除。 - 临时实例的注册、注销、状态变更通常使用 Nacos 自研的 Distro 协议(一种优化的 Gossip 协议,AP 模型)在 Nacos Server 集群节点间进行异步数据同步。这保证了高可用和高性能,但牺牲了短暂的数据一致性。
- Nacos Server 依赖客户端的心跳来判断其存活。服务端会有一个定时任务(
- 持久化实例 (
ephemeral=false):- Nacos Server 不会因为收不到心跳而移除它们。它们的状态变更(注册、注销)需要显式调用 API。
- 持久化实例的数据一致性通常可以通过 Raft 协议(CP 模型)来保证。当处理持久化实例的注册/注销请求时,请求会被转发给 Raft Leader,通过 Raft Log 复制和状态机应用来确保集群中所有节点数据强一致。
- 临时实例 (
-
数据同步 (集群模式):
- AP 模式 (Distro协议 - 主要用于临时实例): 接收到注册请求的节点处理完本地内存后,会将这个实例变更信息(添加或更新)通过 Distro 协议异步发送给集群中的其他节点。其他节点收到同步任务后更新自己的内存数据。
- CP 模式 (Raft协议 - 主要用于持久化实例): 如果是持久化实例,请求可能需要转发给 Raft Leader,Leader 通过 Raft 协议将变更提交,只有当大部分节点确认提交后,Leader 才完成操作并向客户端返回成功。
-
触发事件与推送:
- 当一个
Service的实例列表发生变化(添加、移除、更新)时,Nacos Server 会发布一个内部事件 (ServiceChangeEvent)。 PushService(推送服务) 监听这些事件。如果发现有客户端(通常是服务消费者)通过长连接 (gRPC) 或 UDP 推送机制订阅了这个Service,PushService会将最新的实例列表信息主动推送给这些订阅者。这使得服务发现更加及时。
- 当一个
-
返回响应:
- 服务端处理完成后(对于 AP 模式,本地处理完成即可;对于 CP 模式,Raft 提交成功后),向发起注册请求的客户端返回 HTTP 响应,通常是一个简单的 “ok” 字符串或 JSON 对象表示成功。
总结关键点:
- 注册本质: 客户端向服务端发送包含自身信息的 HTTP PUT 请求。
- 核心数据结构: 服务端内存中维护
Namespace -> Group -> ServiceName -> Service -> List<Instance>的结构。 - 幂等性: 注册操作是幂等的,重复注册同一实例等于更新信息 + 续约(心跳)。
- 临时 vs 持久:
ephemeral参数决定实例类型,影响心跳机制和数据同步协议(AP vs CP)。 - 心跳: 临时实例需要客户端定期发送心跳维持注册。
- 集群同步: AP 模式(Distro)用于临时实例,保证最终一致性和高可用;CP 模式(Raft)可用于持久化实例,保证强一致性。
- 主动推送: 服务端会在实例变更后主动将新列表推送给订阅者。

3763

被折叠的 条评论
为什么被折叠?



