Skip to content

服务注册与发现

单体应用:服务地址固定,配置文件写死 IP:Port 即可
微服务:
• 服务实例数量动态变化(自动扩缩容)
• 容器化部署后 IP 不固定
• 服务故障后需要自动摘除
• 蓝绿部署、金丝雀发布需要动态路由
解决方案:服务注册中心
服务启动 → 向注册中心注册(IP:Port + 健康状态)
服务消费者 → 从注册中心查询可用实例列表 → 客户端负载均衡 → 调用

客户端发现(Client-Side Discovery)

Section titled “客户端发现(Client-Side Discovery)”
服务消费者直接查询注册中心,自己做负载均衡:
Consumer ──→ Registry(查询可用实例)
Consumer ──→ Provider(直接调用,客户端 LB)
代表:Eureka + Ribbon / Nacos + LoadBalancer
优点:无中间跳转,延迟低;负载均衡策略灵活
缺点:服务消费者需要集成发现逻辑(与语言绑定)

服务端发现(Server-Side Discovery)

Section titled “服务端发现(Server-Side Discovery)”
通过负载均衡器/网关路由,消费者不直接与注册中心交互:
Consumer ──→ Load Balancer / API Gateway ──→ Provider
Registry
代表:AWS ALB + ECS、Kubernetes(kube-proxy / CoreDNS)
优点:消费者无需感知注册中心,语言无关
缺点:多一跳延迟;负载均衡器本身需要高可用

Eureka(Netflix 开源,Spring Cloud 经典选择)

Section titled “Eureka(Netflix 开源,Spring Cloud 经典选择)”
特性:AP 系统(可用性优先)
✓ 简单易用,Spring Cloud 原生支持
✓ 去中心化设计,节点对等(Peer-to-Peer)
✓ 自我保护模式
自我保护模式(Self-Preservation):
当 Eureka Server 在短时间内收到的心跳数量低于阈值(85%)时
判断网络发生了抖动而非服务挂了
→ 不再删除注册信息(即使心跳超时)
→ 保护注册表,维持可用性
缺点:
✗ Eureka 2.x 已停止开发
✗ 一致性弱,注册信息可能短暂不一致
✗ 功能单一(只有注册发现,无配置中心)

Nacos(阿里开源,Spring Cloud Alibaba 主推)

Section titled “Nacos(阿里开源,Spring Cloud Alibaba 主推)”
特性:可配置 CP/AP(临时实例 AP,持久实例 CP)
✓ 同时支持服务发现 + 配置中心
✓ 支持推拉模式(服务变更主动推送给客户端)
✓ 支持集群/命名空间多环境隔离
✓ 临时实例(心跳维持)vs 持久实例(主动健康检查)
Nacos 的 AP/CP 选择:
临时实例(Ephemeral=true,默认):
基于 Distro 协议(AP),客户端主动心跳,超时删除
适合:服务实例,允许短暂不一致
持久实例(Ephemeral=false):
基于 Raft 协议(CP),服务端主动健康检查
适合:基础设施节点,需要强一致
特性:CP 系统(一致性优先,基于 Raft)
✓ 强一致性
✓ 健康检查功能强大(HTTP、TCP、gRPC、Script、TTL 等多种方式)
✓ 多数据中心原生支持
✓ Key-Value 存储(可用作简单配置中心)
✓ Service Mesh 支持(Consul Connect)
缺点:
✗ CP 系统在分区时牺牲可用性(选举期间无法写入)
✗ Go 实现,Java 生态集成不如 Nacos

etcd(CoreOS 开源,Kubernetes 使用)

Section titled “etcd(CoreOS 开源,Kubernetes 使用)”
特性:CP 系统,基于 Raft
✓ 高可靠的分布式 KV 存储
✓ Watch 机制(变更实时通知)
✓ Kubernetes 集群状态的唯一存储
不适合用作通用服务注册中心:
设计偏向低频、高一致的场景
大量服务注册/心跳会给 etcd 带来压力
对比项EurekaNacosConsuletcd
一致性模型APAP/CPCPCP
健康检查客户端心跳心跳/主动检测多种方式TTL
配置中心简单是(KV)
多数据中心
维护状态停更活跃活跃活跃
推荐场景老项目维护新项目首选多语言场景K8s 场景

客户端心跳(Pull 模式):
服务实例定期向注册中心发送心跳(一般 30s)
注册中心维护心跳超时时间(一般 90s)
超时未收到心跳 → 摘除实例
实现:Eureka、Nacos 临时实例
问题:
• 心跳正常但服务实际不可用(进程假死、端口被占用但无法处理请求)
• 大量服务时,心跳请求本身是一定的负载
主动健康检查(Push 模式):
注册中心主动探测服务是否存活
HTTP GET / TCP 连接 / gRPC Health Check
实现:Consul、Nacos 持久实例
优点:能检测真实可用性(不只是进程存活)
缺点:注册中心需要维护到每个实例的连接
Kubernetes 的方案(两者结合):
Liveness Probe:探测进程是否存活(失败则重启 Pod)
Readiness Probe:探测服务是否准备好接收请求(失败则从 Endpoints 摘除)
Startup Probe:慢启动服务的专用探测

Nacos 集群(三节点推荐奇数节点):
嵌入式 Derby 数据库 → 生产应改为外部 MySQL(共享存储)
节点间通过 Raft(CP 模式)或 Distro(AP 模式)同步
Eureka 集群(Peer-to-Peer 对等集群):
无 Leader,所有节点对等
注册到一个节点,自动同步到其他节点
问题:同步有延迟,不同节点数据可能短暂不一致
客户端容错:
本地缓存注册信息(注册中心不可用时使用缓存)
多个注册中心节点轮询

Q:Nacos 和 Eureka 有什么区别?

①一致性:Eureka 是 AP,Nacos 可配置 AP(默认)或 CP;②功能:Nacos 同时提供服务发现和配置中心,Eureka 只有服务发现;③推送机制:Nacos 支持服务变更主动推送(长连接),Eureka 是客户端定时拉取;④维护状态:Eureka 2.x 已停止更新,Nacos 仍活跃开发;⑤健康检查:Nacos 支持多种,Eureka 只有客户端心跳。

Q:服务注册中心为什么选 AP 而不是 CP?

服务注册中心的核心价值是让消费者能找到提供者。AP 系统在网络分区时仍能返回(可能略旧的)实例列表,让调用继续进行(即使某些实例可能已不可用,客户端重试可以恢复)。CP 系统在分区时拒绝服务,消费者完全无法获取实例列表,影响更大。注册中心的数据允许短暂不一致(最终一致即可),因此 AP 更合适。

Q:Nacos 的临时实例和持久实例有什么区别?

临时实例基于 Distro 协议(AP),服务实例主动发送心跳维持存活,超时自动删除;适合微服务实例,动态上下线。持久实例基于 Raft 协议(CP),Nacos Server 主动发起健康检查,健康检查失败不删除而是标记不健康;适合不会自动上下线的基础设施节点(如数据库、缓存)。

Q:如果注册中心宕机了,服务调用会中断吗?

不一定中断。客户端(如 Nacos Client)会在本地缓存一份服务实例列表,注册中心宕机后使用本地缓存继续提供服务,不会立即中断调用。但新注册的服务无法被发现,已下线的服务也无法从列表中摘除,可能导致调用错误。因此注册中心仍然需要高可用部署。