这是《Spring Boot 与 Spring Cloud 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 注册中心解决服务实例动态寻址问题。微服务实例会频繁发布、扩容、重启和故障,调用方不能依赖写死的 IP,而应从注册中心获取健康实例列表。
16.1 核心模型
Provider 启动
-> 注册服务名、IP、端口、元数据
-> 定时续约
Consumer 调用
-> 按服务名拉取实例
-> 本地缓存列表
-> 负载均衡选择实例
Provider 下线
-> 注销
或健康检查失败
-> 注册中心标记不可用
核心概念:
| 概念 | 说明 |
|---|---|
| Service | 逻辑服务名 |
| Instance | IP、端口、元数据 |
| Namespace | 环境或租户隔离 |
| Group | 业务分组 |
| Health Check | 存活判断 |
| Subscribe | 消费者订阅变更 |
16.2 常见实现
| 注册中心 | 特点 |
|---|---|
| Nacos | 服务发现与配置中心一体,国内常见 |
| Consul | 多数据中心、健康检查生态 |
| Eureka | AP 风格,Netflix 生态,新项目使用减少 |
| ZooKeeper | CP 风格,常用于中间件 |
| Kubernetes Service | 平台原生服务发现 |
选择考虑:
- 团队已有基础设施;
- 一致性与可用性取舍;
- 健康检查能力;
- 多环境隔离;
- 权限体系;
- 运维成本;
- 云平台集成。
16.3 CAP 取舍
| 模式 | 说明 |
|---|---|
| AP | 优先可用性,允许短暂旧列表 |
| CP | 优先一致性,主从切换时可能拒绝服务 |
服务发现通常更偏向 AP:调用方宁可使用短暂过期的健康列表,也不希望在注册中心抖动时完全无法调用。
但 AP 不等于不要一致,实例异常仍需要通过健康检查、连接失败统计和熔断快速剔除。
16.4 Spring Cloud Discovery
Nacos 依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置:
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: nacos.example.com:8848
namespace: prod
group: TRADE_GROUP
服务提供方无需特殊注解,Spring Boot 应用会自动注册。服务消费方可通过 DiscoveryClient 查询:
@Service
public class InstanceService {
private final DiscoveryClient discoveryClient;
public List<ServiceInstance> instances() {
return discoveryClient.getInstances("inventory-service");
}
}
16.5 健康检查
常见模式:
| 模式 | 说明 |
|---|---|
| 心跳续约 | Provider 定时向注册中心上报 |
| 注册中心主动探测 | Consul 健康检查 |
| Kubernetes 探针 | liveness/readiness |
| 应用自检 | /actuator/health |
推荐同时区分:
| 探针 | 含义 |
|---|---|
| liveness | 进程是否需要重启 |
| readiness | 是否接收流量 |
| startup | 是否完成启动 |
发布时应先改 readiness 为 not ready,等流量排空再停进程。
16.6 实例状态
实例元数据建议:
spring:
cloud:
nacos:
discovery:
metadata:
version: "1.8.0"
zone: cn-east-1a
weight: "100"
可用于灰度、同机房优先、金丝雀发布。更通用的做法是通过部署平台控制 readiness,而不是在每个应用手写上下线接口。
16.7 服务列表缓存
消费者通常会本地缓存服务列表,并订阅推送变更。好处:
- 注册中心故障时仍可调用;
- 减少查询压力;
- 降低延迟。
风险:
- 短暂旧实例;
- 客户端负载均衡状态不一致;
- 推送风暴;
- 注册中心恢复后需要同步。
调用方仍必须有连接失败重试和熔断,不能假设列表永远正确。
16.8 多环境隔离
常见隔离维度:
Namespace:dev / test / prod
Group:trade / search / payment
Cluster:public / internal
严禁测试服务注册到生产 namespace。配置建议:
- 生产地址通过环境变量注入;
- namespace 与部署平台绑定;
- 注册中心账号按环境隔离;
- 权限最小化;
- 上线前校验服务列表。
16.9 注册中心高可用
部署:
nacos / consul cluster
3 或更多节点
前端负载均衡
数据持久化
监控与备份
故障演练:
- 停一个注册中心节点;
- 网络分区;
- 注册中心全部不可用;
- 恢复后观察状态同步。
验收标准:
- 服务注册不失败;
- 消费者可使用本地缓存;
- 实例恢复后自动同步;
- 无重复注册或脏实例;
- 监控告警及时。
16.10 常见问题
| 问题 | 排查 |
|---|---|
| 服务找不到 | namespace、group、服务名 |
| 调到下线实例 | 健康检查、readiness、缓存 |
| 重复注册 | 网卡多 IP、实例 ID |
| 注册慢 | 心跳、网络、启动就绪顺序 |
| 生产看到测试实例 | 环境隔离失效 |
| 实例列表抖动 | GC、健康检查超时、探针过严 |
多网卡场景应显式指定 IP:
spring.cloud.nacos.discovery.ip=10.0.10.11
本章小结
注册中心提供动态服务发现能力,核心是服务名、实例、健康检查和订阅推送。选型要考虑 CAP 取舍、环境隔离、健康检查和运维成本。消费者必须本地缓存列表并配合负载均衡、失败重试与熔断,发布时要正确处理 readiness,避免调用下线实例。
思考题
- 服务发现为什么通常偏向 AP?
- liveness 和 readiness 有什么区别?
- 消费者为什么需要缓存服务列表?
- 如何避免测试服务注册到生产?
- 调用到已下线实例时如何排查?