2. 服务注册与发现工程实践
服务注册与发现是微服务架构的“通讯录”。服务实例启动后把自己的地址写入注册中心,消费者通过注册中心查询可用实例列表,再借助客户端负载均衡发起调用。注册中心一旦不可用,整个调用链会迅速退化,因此工程实践的重点不只是“能注册”,而是“选型合理、部署高可用、健康检查准确、异常时行为可控”。本节围绕 Eureka、Consul、Nacos 的差异,注册中心高可用部署,以及健康检查与自我保护机制展开。
一、三种注册中心的核心差异
Eureka 是 Netflix 开源的 AP 型注册中心,强调可用性:节点之间通过复制同步注册信息,客户端本地缓存服务列表,即使注册中心短时不可用,调用仍可依靠缓存继续。它采用客户端心跳(默认 30 秒)判断实例存活,并带有自我保护机制。Consul 基于 Raft 协议,是 CP 型,提供强一致性的 KV、服务发现和健康检查,支持 DNS 与 HTTP 两种查询方式,健康检查类型丰富(脚本、HTTP、TCP、TTL)。Nacos 同时支持 AP 与 CP 两种一致性模式,集服务发现与配置管理于一体,支持临时实例(心跳)与持久实例(服务端主动探测),并提供控制台、权重、元数据、命名空间与分组等能力,在国内生态中使用广泛。
| 维度 | Eureka | Consul | Nacos |
|---|---|---|---|
| 一致性模型 | AP | CP(Raft) | AP/CP 可选 |
| 健康检查 | 客户端心跳 | 服务端多种探测 | 心跳 + 服务端探测 |
| 配置中心 | 无 | 有 KV | 内置配置管理 |
| 控制台 | 简单 | 有 | 功能完善 |
| 典型场景 | Spring Cloud Netflix 体系 | 多语言、强一致需求 | Spring Cloud Alibaba 体系 |
选型建议:已有 Spring Cloud Netflix 存量系统可继续用 Eureka;需要强一致、多语言、DNS 发现可选 Consul;新建项目、需要配置中心一体化、希望有完善控制台,优先 Nacos。
二、注册中心高可用部署
单节点注册中心是单点故障,生产必须集群化。Eureka 采用 peer-to-peer 复制,节点之间互相注册;Consul 用 Raft,通常 3 或 5 个 Server 节点;Nacos 集群依赖 MySQL 存储,多个 Nacos 节点共享同一数据库,前面挂负载均衡。
以 Nacos 三节点集群为例,关键配置如下:
# application.properties(每个节点)
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://192.168.1.10:3306/nacos_config?useUnicode=true&characterEncoding=utf8&autoReconnect=true
db.user=nacos
db.password=nacos
# cluster.conf(三节点)
192.168.1.11:8848
192.168.1.12:8848
192.168.1.13:8848
客户端配置多个地址,避免单点:
spring.cloud.nacos.discovery.server-addr=192.168.1.11:8848,192.168.1.12:8848,192.168.1.13:8848
Eureka 集群则通过 eureka.client.service-url.defaultZone 互相指向其他节点,例如节点 A 指向 B、C,节点 B 指向 A、C,形成对等复制。Consul 集群使用 consul join 将 Server 节点加入同一 Raft 组,并保证奇数节点数以获得多数派容错。
三、健康检查与自我保护机制
健康检查决定“哪些实例可以被调用”。Eureka 默认客户端每 30 秒发送心跳,服务端 90 秒未收到心跳则剔除实例。当心跳丢失比例超过阈值(默认 85%),Eureka 进入自我保护模式,停止剔除实例,避免网络抖动导致大量误删。自我保护是双刃剑:网络分区时保护了实例列表,但也可能让消费者调用到已宕机实例,因此需要配合客户端重试与熔断。
Nacos 临时实例使用心跳,默认 5 秒一次,15 秒未收到标记不健康,30 秒未收到则剔除;持久实例由服务端主动探测。Consul 健康检查可配置 HTTP 探测:
{
"service": {
"name": "order-service",
"port": 8081,
"check": {
"http": "http://192.168.1.21:8081/actuator/health",
"interval": "10s",
"timeout": "3s",
"deregister_critical_service_after": "30s"
}
}
}
Spring Boot 应用应暴露 /actuator/health,并让注册中心的健康检查指向该端点,而不是仅依赖端口存活。这样数据库连接失败、依赖不可用等业务级异常也能反映到实例状态。
四、工程实践中的关键判断
部署完成后,需要验证三件事:一是注册中心集群任意节点宕机后,服务仍能注册与发现;二是实例被强制下线后,消费者能在预期时间内不再调用它;三是网络抖动时,自我保护或健康检查行为符合预期。可以通过控制台观察实例列表、健康状态与心跳时间,也可以直接调用注册中心 API 查询。
下面这张图概括了服务注册、健康检查、实例剔除与消费者拉取列表之间的信号关系,帮助理解注册中心在调用链中的位置。
从图中可以看到,注册中心位于服务实例与消费者之间,承担注册、心跳、健康检查、列表拉取与剔除职责。高可用部署保证注册中心自身不成为单点,健康检查保证列表中的实例真实可用,自我保护则在网络异常时避免误删。三者配合,才能让服务发现既稳定又准确。
最后给出一个可执行的验证清单:启动三节点注册中心,停掉其中一个节点,观察服务是否仍能注册与发现;启动两个服务实例,停掉一个,观察消费者是否在剔除时间内停止调用;模拟网络延迟,观察心跳与健康检查状态变化。通过控制台和日志确认行为符合预期,才算完成注册与发现的工程落地。