一、核心概念

1. Eureka 架构简述

Eureka 是 Netflix 开源的服务注册与发现组件,广泛用于 Spring Cloud 微服务架构中。其核心角色包括:

  • Eureka Server:服务注册中心,负责维护服务实例的注册信息。
  • Eureka Client:服务提供者和服务消费者,向 Eureka Server 注册自身,并发现其他服务。

2. 心跳检测(Heartbeat / Renewal)

  • 定义:Eureka Client 定期(默认每30秒)向 Eureka Server 发送“心跳”(Renew)请求,表明自己“还活着”。
  • 作用:Server 通过心跳判断服务实例是否健康。若在一定时间内未收到心跳,Server 会将该实例从注册表中剔除(默认90秒未收到心跳即认为失效)。
  • 协议:基于 HTTP 的 REST 调用。

3. 自我保护机制(Self-Preservation Mode)

  • 触发条件:当 Eureka Server 在某个统计周期内(默认15分钟)收到的心跳失败率超过阈值(默认85%),即“预期心跳数 × 0.85”时,进入自我保护模式。
  • 行为
    • 不再剔除“长时间未收到心跳”的服务实例。
    • 控制台显示 EMERGENCY! EUREKA IS IN SELF PRESERVATION MODE
  • 目的:防止因网络分区、短暂抖动等导致大量健康服务被误删,保障系统可用性。

一句话总结
心跳是“我还活着”的信号;自我保护是“我怀疑网络有问题,先别删服务” 的防御机制。


二、操作步骤(详细实践)

步骤 1:搭建 Eureka Server

1.1 创建 Spring Boot 项目,添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
</dependencies>

1.2 配置 application.yml

server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false  # Eureka Server 不注册自己
    fetch-registry: false        # 不从其他节点拉取注册信息(单机)
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  server:
    enable-self-preservation: true  # 开启自我保护(默认开启)
    eviction-interval-timer-in-ms: 60000  # 清理失效实例的间隔(默认60秒)

1.3 启动类添加注解

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

启动后访问:http://localhost:8761,查看 Eureka 控制台。


步骤 2:创建 Eureka Client(服务提供者)

2.1 添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>

2.2 配置 application.yml

server:
  port: 8081

spring:
  application:
    name: service-provider

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    lease-renewal-interval-in-seconds: 30     # 心跳间隔(默认30秒)
    lease-expiration-duration-in-seconds: 90  # 服务失效时间(默认90秒)

2.3 启动类

@SpringBootApplication
@EnableEurekaClient
public class ServiceProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceProviderApplication.class, args);
    }
}

2.4 添加一个简单接口

@RestController
public class ProviderController {
    @GetMapping("/hello")
    public String hello() {
        return "Hello from Provider!";
    }
}

步骤 3:验证心跳与自我保护

3.1 启动服务

  1. 启动 Eureka Server(8761)
  2. 启动 service-provider(8081)

3.2 查看控制台

  • Eureka 控制台显示 1 INSTANCE(S) OF 1 SERVICE(S) UP,表示服务已注册。
  • 日志中可看到 Client 每 30 秒发送一次心跳:
    Renew: service-provider sending renewal to eureka-server
    

3.3 触发自我保护(模拟网络问题)

  • 停止所有 Eureka Client(或断网)。
  • 等待一段时间(约2-3分钟),观察 Eureka Server 控制台:
    • 出现红色警告:EMERGENCY! EUREKA IS IN SELF PRESERVATION MODE
    • 已注册的服务不会立即消失,而是保留。

⚠️ 注意:自我保护是“宁可错保,不可错删”的策略。


三、常见错误与解决方案

错误现象 原因 解决方案
Cannot execute request on any known server Client 无法连接 Eureka Server 检查 eureka.client.service-url.defaultZone 是否正确,防火墙是否开放
服务注册成功但不显示 配置错误或网络问题 检查 spring.application.name 是否一致,Server 是否启用
心跳频繁失败 网络延迟高或 GC 停顿 调整 lease-renewal-interval-in-secondslease-expiration-duration-in-seconds
自我保护频繁触发 心跳间隔过短或实例过多 优化网络,增加实例,或适当调大失效时间

四、注意事项

  1. 心跳间隔与失效时间

    • 默认 30 秒心跳,90 秒失效。生产环境可根据网络质量调整,如改为 15/45 秒。
    • 设置过短会增加 Server 压力,过长则故障发现慢。
  2. 自我保护不可关闭(生产环境)

    • eureka.server.enable-self-preservation=false 仅用于测试,生产环境必须开启。
  3. 多节点部署

    • 生产环境应部署 Eureka Server 集群(至少3节点),避免单点故障。
  4. 客户端缓存

    • Eureka Client 会缓存服务列表,默认每30秒更新一次(eureka.client.registry-fetch-interval-seconds)。

五、使用技巧

  • 自定义实例ID

    eureka:
      instance:
        instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    
  • 健康检查集成: 使用 Spring Boot Actuator,Eureka 会自动检测 /actuator/health 状态。

  • 优雅下线: 在服务关闭前调用:

    @Autowired
    private EurekaClient eurekaClient;
    
    public void shutdown() {
        eurekaClient.shutdown();
    }
    

    或发送 DELETE 请求到 Eureka Server。


六、最佳实践与性能优化

1. 集群部署 Eureka Server

  • 至少3个节点,相互注册,提高可用性。
  • 配置:
    eureka:
      client:
        service-url:
          defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/,http://peer3:8763/eureka/
    

2. 调整心跳与清理频率

# Client 配置
eureka:
  instance:
    lease-renewal-interval-in-seconds: 15
    lease-expiration-duration-in-seconds: 45

# Server 配置
eureka:
  server:
    eviction-interval-timer-in-ms: 30000  # 每30秒清理一次

3. 监控与告警

  • 集成 Prometheus + Grafana 监控 Eureka 状态。
  • 对“自我保护模式”触发设置告警。

4. 与 Ribbon/Feign 集成

  • Feign 默认集成 Ribbon,自动从 Eureka 获取服务列表并负载均衡。

5. 性能优化建议

  • 避免注册过多小服务,合理拆分。
  • 使用 @RefreshScope 动态刷新配置,减少重启。
  • 定期清理已下线服务(手动或脚本)。

七、总结

机制 作用 推荐配置
心跳检测 维持服务存活状态 15~30秒
服务失效 清理不健康实例 45~90秒
自我保护 防止误删服务 必须开启
集群部署 提高可用性 ≥3节点

实践建议

  • 开发环境可用单节点 + 关闭自我保护。
  • 生产环境必须集群 + 开启自我保护 + 合理调参。

掌握 Eureka 的心跳与自我保护机制,是构建高可用微服务系统的基石。建议在测试环境中多模拟故障场景(如断网、GC、重启),加深理解。