服务注册与发现
为什么需要服务注册与发现
Section titled “为什么需要服务注册与发现”单体应用:服务地址固定,配置文件写死 IP:Port 即可
微服务: • 服务实例数量动态变化(自动扩缩容) • 容器化部署后 IP 不固定 • 服务故障后需要自动摘除 • 蓝绿部署、金丝雀发布需要动态路由
解决方案:服务注册中心 服务启动 → 向注册中心注册(IP:Port + 健康状态) 服务消费者 → 从注册中心查询可用实例列表 → 客户端负载均衡 → 调用服务发现的两种模式
Section titled “服务发现的两种模式”客户端发现(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)优点:消费者无需感知注册中心,语言无关缺点:多一跳延迟;负载均衡器本身需要高可用主流注册中心对比
Section titled “主流注册中心对比”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),服务端主动健康检查 适合:基础设施节点,需要强一致Consul(HashiCorp 开源)
Section titled “Consul(HashiCorp 开源)”特性:CP 系统(一致性优先,基于 Raft) ✓ 强一致性 ✓ 健康检查功能强大(HTTP、TCP、gRPC、Script、TTL 等多种方式) ✓ 多数据中心原生支持 ✓ Key-Value 存储(可用作简单配置中心) ✓ Service Mesh 支持(Consul Connect)
缺点: ✗ CP 系统在分区时牺牲可用性(选举期间无法写入) ✗ Go 实现,Java 生态集成不如 Nacosetcd(CoreOS 开源,Kubernetes 使用)
Section titled “etcd(CoreOS 开源,Kubernetes 使用)”特性:CP 系统,基于 Raft ✓ 高可靠的分布式 KV 存储 ✓ Watch 机制(变更实时通知) ✓ Kubernetes 集群状态的唯一存储
不适合用作通用服务注册中心: 设计偏向低频、高一致的场景 大量服务注册/心跳会给 etcd 带来压力| 对比项 | Eureka | Nacos | Consul | etcd |
|---|---|---|---|---|
| 一致性模型 | AP | AP/CP | CP | CP |
| 健康检查 | 客户端心跳 | 心跳/主动检测 | 多种方式 | TTL |
| 配置中心 | 否 | 是 | 简单 | 是(KV) |
| 多数据中心 | 否 | 是 | 是 | 是 |
| 维护状态 | 停更 | 活跃 | 活跃 | 活跃 |
| 推荐场景 | 老项目维护 | 新项目首选 | 多语言场景 | K8s 场景 |
心跳机制与健康检查
Section titled “心跳机制与健康检查”客户端心跳(Pull 模式): 服务实例定期向注册中心发送心跳(一般 30s) 注册中心维护心跳超时时间(一般 90s) 超时未收到心跳 → 摘除实例
实现:Eureka、Nacos 临时实例 问题: • 心跳正常但服务实际不可用(进程假死、端口被占用但无法处理请求) • 大量服务时,心跳请求本身是一定的负载
主动健康检查(Push 模式): 注册中心主动探测服务是否存活 HTTP GET / TCP 连接 / gRPC Health Check
实现:Consul、Nacos 持久实例 优点:能检测真实可用性(不只是进程存活) 缺点:注册中心需要维护到每个实例的连接
Kubernetes 的方案(两者结合): Liveness Probe:探测进程是否存活(失败则重启 Pod) Readiness Probe:探测服务是否准备好接收请求(失败则从 Endpoints 摘除) Startup Probe:慢启动服务的专用探测服务注册中心的高可用
Section titled “服务注册中心的高可用”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)会在本地缓存一份服务实例列表,注册中心宕机后使用本地缓存继续提供服务,不会立即中断调用。但新注册的服务无法被发现,已下线的服务也无法从列表中摘除,可能导致调用错误。因此注册中心仍然需要高可用部署。