服务注册发现:Eureka源码剖析(10)核心机制之Eureka Server网络故障时的自我保护机制
- 自我保护机制是什么?
在eureka server中,他假定正常情况下肯定有大于85%的服务实例能够保持正常的心跳,最近1分钟内少于85%的服务实例心跳成功,eureka开发团队认为,此时大概率是eureka server自己的网络故障了,此时再进行过期实例剔除都会是误伤,于是就不再对故障实例剔除。这就叫进入了自我保护机制。
自我保护的实现原理
eureka自我保护机制的代码实现比较零散,逻辑分散的各处,需要仔细翻阅源码才能找到,笔者也是花了几个小时(一个开源项目里的代码质量还真是参差不齐。。。)
在上篇文章讲解的自动摘除服务实例的实现方法evit中,在最开始进行了当前是否进入自我保护状态的判断
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public boolean isLeaseExpirationEnabled() {
if (!isSelfPreservationModeEnabled()) {
// The self preservation mode is disabled, hence allowing the instances to expire.
return true;
}
// 如果开启自我保护机制 就会走下面的逻辑
// numberOfRenewsPerMinThreshold = 服务实例数量 * 2 * 0.85 期望值,最少有85%的实例发送心跳 心跳30秒1次,于是就 *2
// getNumOfRenewsInLastMin() 返回的就是 最近1分钟实际心跳成功的服务实例数
// 是通过 MeasuredRate 组件 + renew时触发来实现的
// 这个判断的意思也就明了了,最近1分钟实际心跳成功的服务实例数 > 要大于85% ,这个时候才会允许处理过期服务实例
// 为啥这么做?
// 这也就是eureka所谓的自我保护机制的实现了。他假定正常情况下肯定会有超过85%的服务实例能够心跳成功成功的
// 如果小于85%,那么就有可能是eureka server自己的网络出现故障了,此时就不能再剔除过期实例了,因为可能是误伤
// 这种状态下不剔除服务实例,这个操作,就是进入自我保护模式这个动作,达到了自我保护这个状态和效果,此时eureka控制台里也会显示出那行红字
// 为什么测试环境非常容易触发自我保护机制呢?
// 测试环境频繁的有服务实例注册、销毁,生命周期非常的短,可能连第二次心跳都没进行,这就导致最近一分钟内的服务实例心跳成功数大大降低
// 非常有可能低于85%,一旦低于85%就会进入自我保护模式。
// 测试环境这种情况是持续存在的,所以就会显示出eureka持续进入自我保护模式了
// 这个方法 返回true,说明正常;返回false,就是进入了自我保护模式了
// 这点儿注意,与Spring cloud netflix eureka的实现方式相同,但返回值的含义是相反的
return numberOfRenewsPerMinThreshold > 0 && getNumOfRenewsInLastMin() > numberOfRenewsPerMinThreshold;
}numberOfRenewsPerMinThreshold 服务实例数量 * 2 * 0.85 期望值,最少有85%的实例发送心跳 心跳30秒1次,于是就 *2
getNumOfRenewsInLastMin() 返回的就是 最近1分钟实际心跳成功的服务实例数
是通过 MeasuredRate 组件 + renew时触发来实现的
也就是每次心跳成功都会对MeasuredRate 内的数值加1,而每隔1分钟,MeasuredRate 组件会把自己的数值清零如果 getNumOfRenewsInLastMin() > numberOfRenewsPerMinThreshold,也就是最近1分钟,少于85%的服务实例心跳成功,就意味着进入了自我保护状态了
这个方法 返回true,说明正常;返回false,就是进入了自我保护模式了
注意,与Spring cloud netflix eureka的实现方式相同,但返回值的含义是相反的
为什么测试环境非常容易触发自我保护机制呢?
测试环境频繁的有服务实例注册、销毁,生命周期非常的短,可能连第二次心跳都没进行,这就导致最近一分钟内的服务实例心跳成功数大大降低,非常有可能低于85%,一旦低于85%就会进入自我保护模式。 测试环境这种情况是持续存在的,所以就会显示出eureka持续进入自我保护模式了
注意
自我保护机制的实现,采用了硬编码的方式强制指定了30秒的心跳周期,所以在实际生产中,我们要么不用这个自我保护模式,要么就不要修改心跳间隔,否则逻辑就错乱了