背景:项目使用的是SpringCloud微服务体系,eureka作为注册中心,SpringBoot版本2.0.4.RELEASE
。
1. eureka自我保护
Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来,让这些实例不会过期,但是在保护期内如果服务刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,此时会调用失败。
自我保护模式被激活的条件是:在 1 分钟后,Renews (last min) < Renews threshold。
- Renews threshold:Eureka Server 期望每分钟收到客户端实例续约的总数。
- Renews (last min):Eureka Server 最后 1 分钟收到客户端实例续约的总数。
Eureka 的自我保护模式是有意义的,该模式被激活后,它不会从注册列表中剔除因长时间没收到心跳导致租期过期的服务,而是等待修复,直到心跳恢复正常之后,它自动退出自我保护模式。这种模式旨在避免因网络分区故障导致服务不可用的问题。例如,两个客户端实例 C1 和 C2 的连通性是良好的,但是由于网络故障,C2 未能及时向 Eureka 发送心跳续约,这时候 Eureka 不能简单的将 C2 从注册表中剔除。因为如果剔除了,C1 就无法从 Eureka 服务器中获取 C2 注册的服务,但是这时候 C2 服务是可用的。
注:经过测试,若关闭自我保护后,因为网络原因,eureka未收到C2心跳,将C2下线,但当网络好了后,C2还是会注册到eureka上。
2. 自我保护的bug
不通过curl从eureka优雅的关闭的服务,直接频繁kill -9关闭服务会导致阈值飙升,开启自我保护。
由于项目上线频率高,使得了eureka的Renews threshold升高。导致eureka开启自我保护。而某个项目重启时间长(该项目部分节点机器重启期间,eureka因为开启自我保护,不会移除节点)会导致请求被路由到重启的机器上,导致请求失败。
解决方案:一个是关闭自我保护, 一个是eureka版本升到1.9.17,也就是springcloud升到2.2.2.RELEASE以上,这个版本是2020.03发布的。
在版本不好升级的情况下,可以关闭自我保护。