在微服务架构中,服务实例的网络地址是动态变化的——扩容、缩容、故障转移都会导致实例的 IP 和端口频繁变更。服务注册与发现正是解决这一问题的核心机制:每个服务启动时,将自己的元数据(IP、端口、健康状态等)注册到注册中心;调用方通过服务名即可从注册中心获取可用实例列表,实现透明化的远程调用。
Spring Cloud 对服务注册与发现提供了统一的抽象,并支持多种注册中心实现。目前最主流的选择是 Nacos 和 Eureka,下面分别说明它们的使用方式与差异。
16.2.1 Eureka:Netflix 出品的经典方案
Eureka 是 Spring Cloud Netflix 体系中的注册中心组件,遵循 AP 原则(可用性优先)。它由 Eureka Server 和 Eureka Client 两部分组成,客户端启动时向 Server 注册,并通过心跳维持租约。
1. 搭建 Eureka Server
在 Spring Boot 项目中引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
启动类添加 @EnableEurekaServer:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
配置 application.yml:
server:
port: 8761
eureka:
client:
register-with-eureka: false # 服务端不注册自身
fetch-registry: false
server:
enable-self-preservation: true # 开启自我保护模式
2. 服务提供者接入 Eureka
引入客户端依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置服务名称与注册中心地址:
spring:
application:
name: order-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
启动后服务会自动注册到 Eureka Server,控制台即可看到注册实例。
3. Eureka 的自我保护机制
当 Eureka Server 短时间内丢失大量心跳时(例如网络分区),会进入自我保护模式:不再剔除任何实例,以避免误删正常服务。这是 CAP 中 AP 的体现,保证可用性但可能返回已下线的实例。生产环境中,通常需要结合健康检查和客户端重试机制(如 Ribbon/LoadBalancer 的重试)来保证调用成功率。
16.2.2 Nacos:阿里巴巴开源的统一配置与服务发现中心
Nacos(Dynamic Naming and Configuration Service)将 服务注册发现 与 配置管理 融合在一起,支持 CP 与 AP 模式切换,并且具备健康检查、动态权重、流量管理等更丰富的功能。在国内企业中使用广泛。
1. 搭建 Nacos Server
Nacos 提供独立服务端,可直接下载安装包或使用 Docker 部署:
docker run -d --name nacos -e MODE=standalone -p 8848:8848 nacos/nacos-server:latest
单机模式启动后,访问 http://localhost:8848/nacos,默认账号密码 nacos/nacos。
2. 服务提供者接入 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: localhost:8848
启动类无需特殊注解,服务会自动注册到 Nacos。在 Nacos 控制台“服务管理”中可查看实例列表。
3. Nacos 的健康检查与权重
Nacos 支持两种健康检查方式:
- 临时实例(ephemeral=true,默认):采用客户端心跳上报,类似 Eureka,适用于 AP 场景,网络中断后一定时间会剔除。
- 持久实例(ephemeral=false):由服务端主动探测,即便心跳丢失也不会自动剔除,适用于 CP 场景。
你可以动态调整实例权重(0~1),配合负载均衡实现灰度发布或流量切分。
16.2.3 服务发现与负载均衡的集成
无论是 Eureka 还是 Nacos,注册中心负责维护实例列表,客户端的负载均衡由 Spring Cloud LoadBalancer 完成。在 RestTemplate 或 WebClient 的 Bean 上添加 @LoadBalanced 后,就可以使用服务名进行调用:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
// 调用时使用服务名代替 IP:Port
String result = restTemplate.getForObject("http://order-service/orders/1", String.class);
OpenFeign 也默认集成了负载均衡,只需声明接口即可:
@FeignClient(name = "order-service")
public interface OrderClient {
@GetMapping("/orders/{id}")
Order getOrder(@PathVariable Long id);
}
16.2.4 Eureka 与 Nacos 的对比与选型建议
| 特性 | Eureka | Nacos |
|------|--------|-------|
| CAP 模型 | AP(自我保护机制) | AP + CP 可切换 |
| 配置管理 | 无(需结合 Spring Cloud Config) | 内置统一配置中心 |
| 健康检查 | 仅心跳 | 支持心跳与服务端主动探测 |
| 动态权重与流量管理 | 不直接支持 | 支持实例权重、元数据打标 |
| 控制台功能 | 基础实例查看 | 功能丰富(服务管理、配置管理、命名空间) |
| 项目活跃度 | Netflix 宣布维护模式,但社区仍可用 | Alibaba 持续维护,更新活跃 |
| 部署复杂度 | 需要额外搭建 Eureka Server | 独立服务端,部署简单 |
选型建议:
- 如果团队已有 Spring Cloud Netflix 体系,且注册中心功能需求简单,可以继续使用 Eureka。
- 如果希望减少组件数量(注册中心 + 配置中心合一),或需要动态权重、灰度发布等高级功能,Nacos 是更优的选择,尤其在新项目中已成为主流。
- 在国内生产环境中,Nacos 结合 Spring Cloud Alibaba 生态的完整性(Sentinel、Seata、RocketMQ)优势明显。
16.2.5 实践中的注意事项
- 高可用部署:Eureka Server 和 Nacos Server 都不要单点。Eureka 可通过多节点互相注册实现集群;Nacos 推荐至少部署三个节点组成集群,并使用 MySQL 做持久化。
- 元数据与分组:为服务实例添加自定义元数据(如
version: v2),可以结合负载均衡策略实现多版本路由。Nacos 支持命名空间(Namespace)和分组(Group),方便多环境隔离。 - 服务剔除策略:注意配置合适的心跳间隔与过期时间。默认情况下,Eureka 剔除时间较长(90s),Nacos 临时实例默认 30s 不健康后剔除。可根据业务容忍度调整。
- 注册耦合:服务启动时会立即注册,停止时应优雅下线。可以使用
spring.cloud.nacos.discovery.watch.enabled=true监听变更,或利用 Actuator 的service-registry端点主动注销。 - 保护机制:理解 Eureka 的自我保护模式和 Nacos 的实例类型,避免在网络闪断时误剔除大量服务,导致调用连锁失败。
服务注册与发现是微服务体系的中枢神经。无论选择 Eureka 还是 Nacos,关键是确保注册中心自身的高可用,并配合合理的健康检查与负载均衡策略,使整个系统具备弹性与韧性。在后续章节中,我们将看到服务发现与 Spring Cloud Gateway、Feign、Sentinel 等组件如何协同工作,构建完整的微服务调用链。