Nacos - 服务发现

Nacos 的服务发现(Service Discovery)是指服务消费者(Consumer)如何获取服务提供者(Provider)地址列表的过程。

Nacos 采用了 "主动拉取 + 被动推送" 相结合的机制,确保了服务发现的实时性 和高可用性。


一、 服务发现的整体架构

服务发现主要涉及三个角色:

  1. 服务提供者 (Provider):注册自己的 IP/端口到 Nacos。
  2. Nacos Server:保存服务注册表,并感知实例状态变化。
  3. 服务消费者 (Consumer):从 Nacos 获取地址列表,并监听变化。

二、 详细流程详解

1. 消费者初始化与订阅 (Subscription)

当一个微服务启动并需要调用其他服务时:

  • 查询缓存:消费者首先会检查本地内存中是否有目标服务的实例列表。
  • 发起订阅:如果没有或需要更新,消费者会向 Nacos Server 发起订阅请求(Subscribe)。
  • 版本差异 :
    • Nacos 1.x:通过 HTTP 轮询定时拉取,并开启一个 UDP 端口接收服务端的推送。
    • Nacos 2.x :通过 gRPC 双向流 建立长连接。客户端发送 ServiceQueryRequest,并在服务端注册该连接的订阅关系。

2. 服务端获取与过滤 (Server Side)

Nacos Server 收到查询请求后:

  • 检索注册表 :从内存 Map(Service -> Cluster -> Instances)中找到对应的实例。
  • 健康检查过滤 :
    • 只返回 healthy=true(健康)的实例。
    • 只返回 enabled=true(启用)的实例。
  • 选择集群:根据客户端配置的集群名称(Cluster Name),优先返回同集群的实例(就近访问策略)。

3. 客户端本地缓存 (Local Cache)

这是 Nacos 保证高可用的关键:

  • 内存缓存 :客户端将获取到的 ServiceInfo(包含实例列表)保存到内存中的 ServiceInfoHolder。
  • 磁盘缓存 :同时将数据异步写入本地磁盘文件(路径通常在 ${user.home}/nacos/naming/${namespace})。
  • 容灾逻辑 :如果 Nacos Server 全部宕机,消费者会直接读取本地磁盘文件,保证业务不中断。

4. 实时更新机制 (Push & Pull)

为了保证消费者拿到的地址是最新的,Nacos 采用了以下策略:

  • 被动接收推送 (Push) :
    • 一旦服务提供者下线、故障或有新节点加入,Nacos Server 会触发 ServiceChangeEvent。
    • Nacos 2.x 会通过已建立的 gRPC 长连接,主动将最新的实例列表推送到消费者(Push)。这种方式是毫秒级的。
  • 定时主动拉取 (Pull) :
    • 作为补偿机制,客户端内部有一个定时任务(默认每 10 秒或根据配置),会检查本地数据的版本,必要时重新拉取,防止因网络闪断导致的推送丢失。

5. 客户端负载均衡 (Load Balance)

服务发现拿到的是一个列表(比如 3 个 IP),具体调用哪一个由客户端决定:

  • 在 Spring Cloud 环境中,通常配合 Spring Cloud LoadBalancer 或 Ribbon。
  • 根据 Nacos 返回的 Weight(权重) 进行加权随机访问。
  • 执行最终的 RPC 调用(如 RestTemplate, Feign, Dubbo)。

三、 核心流程图解

  1. Consumer -> query (gRPC) -> Nacos Server
  2. Nacos Server -> result (Instance List) -> Consumer
  3. Consumer -> save -> Memory & Disk Cache
  4. (当 Provider 发生变化时)
  5. Nacos Server -> push (New List) -> Consumer
  6. Consumer -> update -> Local Cache

四、 关键特性总结

特性 说明
实时性 2.x 基于 gRPC 长连接推送,几乎瞬时感知服务变化。
高可用 (Self-Protection) 就算 Nacos 集群挂了,客户端靠本地缓存(磁盘文件)也能正常调用服务。
就近访问 支持按 Cluster 归类,优先调用同机房/同地域的服务,降低延迟。
权重调整 支持在 Nacos 控制台动态修改实例权重,实现灰度发布或平滑下线。

五、 Nacos 是如何支撑大规模服务发现的?

  1. 分级存储:Namespace -> Group -> Service -> Cluster -> Instance,结构清晰。
  2. UDP/gRPC 推送:相比全量拉取,推送极大减少了网络带宽消耗。
  3. 写时复制 (CopyOnWrite):在更新实例列表时,不影响读取操作,保证高性能。
  4. 压缩传输:在返回大量实例时,Nacos 会对数据进行压缩,减少网络开销。
相关推荐
EatFan6 小时前
Spring Boot 4 落地观察:从 yudao-cloud、matecloud、JPower 看国产脚手架的升级路线与迁移清单
java·spring boot·后端·spring cloud·微服务·后端开发·jdk 21
Maiko Star7 小时前
* LangChain 提示词模板详解:ChatPromptTemplate 的使用与高级特性
java·人工智能·langchain
现任明教教主~9 小时前
Thinkphp站群蜘蛛池SaaS系统YanyvSEO含多用户/积分/六大引擎计费/易支付对接
java·开发语言·spring
一条破秋裤9 小时前
Linux 线程创建:pthread_create 与基本回收
java·linux·运维
布吉岛的石头9 小时前
Java 程序员第 49 阶段5:BERT 预训练目标 MLM+NSP 的工程含义
java·人工智能·深度学习·bert·transformer
摇滚侠10 小时前
《On Java 中文版 基础卷》阅读笔记 对象无处不在 03
java·笔记·python
二十雨辰11 小时前
[学成在线]-01项目背景
java
广州山泉婚姻11 小时前
Go微服务落地:服务通信、注册发现完整实现分享
人工智能·深度学习·微服务
弈栈录11 小时前
Java AI 应用的异步化与高并发设计
java·后端·架构
落魄实习生12 小时前
Agent Scope Java 2.x 系列【2】 ReActAgent
java·开发语言