自我保护机制
2026/1/15大约 5 分钟Eureka自我保护高可用
自我保护机制
一、什么是自我保护
Eureka 的自我保护机制是一种应对网络异常的安全保护措施。当 Eureka Server 在短时间内丢失过多客户端心跳时,会进入自我保护模式,不再剔除任何服务实例。
1.1 触发条件
当最近一分钟收到的心跳数 < 期望心跳数 × 85% 时,触发自我保护。
实际心跳数 < 期望心跳数 × 0.851.2 控制台警告
进入自我保护模式后,Eureka 控制台会显示红色警告:
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT.
RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED
JUST TO BE SAFE.二、为什么需要自我保护
2.1 网络分区问题
在网络分区情况下:
- Eureka Server 收不到心跳
- 但服务之间可能仍然可以正常通信
- 如果剔除服务,会导致不必要的服务不可用
2.2 自我保护的作用
| 场景 | 无自我保护 | 有自我保护 |
|---|---|---|
| 网络分区 | 大量服务被剔除 | 保留所有服务 |
| 服务真正下线 | 正常剔除 | 不剔除(需等待恢复) |
| 网络恢复后 | 服务需重新注册 | 服务信息完整 |
三、自我保护原理
3.1 期望心跳数计算
// 期望每分钟心跳数 = 实例数 × (60 / 心跳间隔) × 续约百分比阈值
expectedNumberOfClientsSendingRenews = instanceCount × 2 × renewalPercentThreshold
// 默认值
// 心跳间隔 = 30秒,所以每分钟2次
// renewalPercentThreshold = 0.853.2 判断逻辑
// 伪代码
public boolean isLeaseExpirationEnabled() {
// 如果关闭自我保护,直接返回 true(允许剔除)
if (!isSelfPreservationModeEnabled()) {
return true;
}
// 计算期望心跳数
int expectedRenewals = getExpectedNumberOfRenewsPerMin();
// 获取实际心跳数
int actualRenewals = getNumOfRenewsInLastMin();
// 实际心跳数 > 期望心跳数 × 阈值,允许剔除
return actualRenewals > expectedRenewals * renewalPercentThreshold;
}3.3 流程图
四、配置自我保护
4.1 服务端配置
eureka:
server:
# 是否开启自我保护(默认 true)
enable-self-preservation: true
# 续约百分比阈值(默认 0.85)
renewal-percent-threshold: 0.85
# 续约阈值更新间隔(毫秒,默认 15分钟)
renewal-threshold-update-interval-ms: 900000
# 剔除任务执行间隔(毫秒,默认 60秒)
eviction-interval-timer-in-ms: 600004.2 客户端配置
eureka:
instance:
# 心跳间隔(秒,默认 30)
lease-renewal-interval-in-seconds: 30
# 服务过期时间(秒,默认 90)
lease-expiration-duration-in-seconds: 904.3 开发环境建议
开发环境建议关闭自我保护,以便快速感知服务下线:
eureka:
server:
# 关闭自我保护
enable-self-preservation: false
# 缩短剔除间隔
eviction-interval-timer-in-ms: 5000
instance:
# 缩短心跳间隔
lease-renewal-interval-in-seconds: 5
# 缩短过期时间
lease-expiration-duration-in-seconds: 15五、自我保护的问题
5.1 问题场景
5.2 解决方案
- 客户端重试:配置重试机制,失败后尝试其他实例
- 熔断降级:使用 Hystrix/Sentinel 进行熔断
- 健康检查:配置更严格的健康检查
// 配置重试
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
// 配置重试拦截器
return restTemplate;
}六、监控自我保护状态
6.1 Actuator 端点
management:
endpoints:
web:
exposure:
include: health,info,eureka6.2 查看状态
访问 http://localhost:8761/actuator/health 查看健康状态。
6.3 控制台信息
Eureka 控制台显示的关键信息:
| 指标 | 说明 |
|---|---|
| Renews threshold | 期望心跳数阈值 |
| Renews (last min) | 最近一分钟实际心跳数 |
| Self preservation | 自我保护状态 |
七、最佳实践
7.1 生产环境
eureka:
server:
# 开启自我保护
enable-self-preservation: true
# 适当调整阈值
renewal-percent-threshold: 0.857.2 开发/测试环境
eureka:
server:
# 关闭自我保护
enable-self-preservation: false
# 快速剔除
eviction-interval-timer-in-ms: 50007.3 配合其他组件
- Ribbon:客户端负载均衡,自动剔除不可用实例
- Hystrix:熔断降级,防止级联故障
- Feign:声明式调用,集成重试机制
八、总结
自我保护机制的核心要点:
- 目的:防止网络分区导致的误剔除
- 触发条件:心跳数低于阈值的 85%
- 行为:停止剔除任何服务实例
- 问题:可能保留已下线的服务
- 解决:配合重试、熔断等机制使用
