本文目录导读:

- 目录导读
- 为什么需要服务注册中心?
- Eureka核心概念
- 环境准备与依赖搭建
- 服务注册中心(Server)代码实现
- 服务提供者(Client)注册实战
- 服务消费者(Consumer)发现与调用
- 高可用集群配置
- 常见问题与FAQ
Spring Cloud Eureka服务注册实战:从零搭建高可用微服务注册中心
目录导读
- 为什么需要服务注册中心? —— 微服务架构的“通讯录”痛点
- Eureka核心概念 —— 服务提供者、消费者与注册中心的三角恋
- 环境准备与依赖搭建 —— Maven依赖、启动类注解全解析
- 服务注册中心(Server)代码实现 —— 三步搞定Eureka Server
- 服务提供者(Client)注册实战 —— 心跳续约与元数据配置
- 服务消费者(Consumer)发现与调用 —— RestTemplate + @LoadBalanced
- 高可用集群配置 —— 多节点互相注册,避免单点故障
- 常见问题与FAQ —— 服务注册不上?心跳超时?一文排雷
为什么需要服务注册中心?
在传统单体应用中,服务间调用通过IP+端口直接写死,但在微服务架构下,服务实例会动态扩缩容、重启迁移,硬编码地址会彻底崩盘。Eureka作为Netflix开源的服务注册中心,相当于整个微服务体系的“实时通讯录”:
- 每个服务启动时向Eureka Server登记自己的IP、端口、服务名
- 服务消费者从Eureka拉取可用服务列表,实现客户端负载均衡
- 通过心跳机制(默认30秒)自动剔除故障节点
关键点:Eureka更偏向“AP”模式(高可用优先),适合非强一致性的业务场景,而Zookeeper则是“CP”模式。
Eureka核心概念
| 角色 | 说明 | 关键动作 |
|---|---|---|
| Eureka Server | 注册中心,存储服务实例信息 | 接收心跳、提供查询接口、剔除过期实例 |
| Eureka Client (Provider) | 提供业务的微服务 | 注册、续约(心跳)、下线通知 |
| Eureka Client (Consumer) | 调用其他服务的微服务 | 拉取注册表、缓存、更新 |
核心配置标签:
eureka.client.register-with-eureka:是否注册自己到注册中心eureka.client.fetch-registry:是否拉取注册表缓存到本地
环境准备与依赖搭建
创建两个Spring Boot模块(这里使用2.3.x版本,兼容Spring Cloud Hoxton.SR12):
父POM核心依赖管理:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR12</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Eureka Server模块依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
Provider/Consumer依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
注意:Spring Boot 2.4+需显式指定
spring-boot-starter-web,否则可能报错。
服务注册中心(Server)代码实现
Step 1:启动类添加注解
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
Step 2:application.yml配置
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false # 不注册自己
fetch-registry: false # 不拉取注册表
server:
enable-self-preservation: false # 开发期关闭自我保护,测试更直观
Step 3:启动并访问
浏览器输入http://localhost:8761,即可看到Eureka的Web控制台,Instances currently registered with Eureka”列表为空。
服务提供者(Client)注册实战
启动类注解:
@SpringBootApplication
@EnableEurekaClient
public class ProviderApplication { ... }
application.yml:
server:
port: 8081
spring:
application:
name: order-service # 服务名,消费者根据此名调用
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true # 注册时使用IP而不是主机名
instance-id: ${spring.cloud.client.ip-address}:${server.port}
lease-renewal-interval-in-seconds: 30 # 心跳间隔
lease-expiration-duration-in-seconds: 90 # 超时剔除时间
写一个测试接口:
@RestController
public class OrderController {
@GetMapping("/order/info")
public String getOrder() {
return "订单服务-8081";
}
}
启动后,Eureka控制台立刻出现ORDER-SERVICE,状态为“UP”,此时可测试心跳续约:日志中会每30秒打印DiscoveryClient_ORDER-SERVICE - Heartbeat。
服务消费者(Consumer)发现与调用
关键步骤:注入RestTemplate并加@LoadBalanced实现负载均衡。
@SpringBootApplication
@EnableEurekaClient
public class ConsumerApplication {
@Bean
@LoadBalanced // 关键:启用Ribbon负载均衡,自动解析服务名
public RestTemplate restTemplate() {
return new RestTemplate();
}
// main方法略
}
Controller调用:
@RestController
public class CallController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/call")
public String call() {
// 直接使用服务名,而非IP+端口
String result = restTemplate.getForObject(
"http://order-service/order/info", String.class);
return "消费者调用结果: " + result;
}
}
验证:启动Consumer(端口8082),访问http://localhost:8082/call,返回“订单服务-8081”,若启动多个Provider实例,Ribbon会轮询分发。
高可用集群配置
单节点注册中心一旦宕机,整个微服务列表将不可用,生产环境必须搭建集群:
创建两个Eureka Server(8761、8762),互相注册:
Server-A配置:
server:
port: 8761
eureka:
client:
service-url:
defaultZone: http://peer2:8762/eureka/ # 注册到另一节点
Server-B配置:
server:
port: 8762
eureka:
client:
service-url:
defaultZone: http://peer1:8761/eureka/
Provider的defaultZone同样配置多个地址,用逗号隔开:http://peer1:8761/eureka/,http://peer2:8762/eureka/,这样任意一个注册中心宕机,服务仍可注册和发现。
常见问题与FAQ
Q1:服务注册失败,控制台报错“Connection refused”
检查Eureka Server端口是否开放,且Provider端的defaultZone地址路径必须包含/eureka/,且末尾反斜杠不能漏。
Q2:服务明明已停止,但Eureka控制台仍显示UP
这是自我保护机制(默认开启),开发建议设为false,生产环境则需关注:
eureka:
server:
enable-self-preservation: false
但注意生产关闭有导致误剔除的风险,需结合监控。
Q3:消费者调用时出现java.net.UnknownHostException: order-service
根本原因:RestTemplate未加@LoadBalanced,导致Spring无法将服务名解析成实际IP,确保注解已加,且引入了spring-cloud-starter-netflix-ribbon(通常随Eureka Client自带)。
Q4:多个服务实例,但负载均衡不生效?
检查是否所有实例的spring.application.name完全相同,Ribbon根据名称+实例数轮询,名称不同会被视为不同服务。
Q5:Eureka的自我保护阶段,剔除节点延迟
心跳丢失超过90秒后,节点才会被剔除,如果频繁重启服务,建议调小lease-renewal-interval-in-seconds。
Eureka服务注册机制的核心就是“注册-心跳-发现-调用”四个动作,通过本文案例,你可以快速搭建起一个具备高可用能力的注册中心,并掌握Provider与Consumer的完整链路,后续可结合Spring Cloud Gateway、Config等组件,构建更完整的微服务生态。注册中心是微服务的第一块基石,做好降级和容错设计永远不嫌早。
(本文所有实践代码均可在Spring Boot 2.3.x + Hoxton.SR12版本下直接运行。)