Eureka目录导航
一、思考
当网络出现大面积故障时,微服务与Server之间无法保持心跳,上述行为就非常危险,由于Server端默认90秒会剔除无心跳的服务,因此服务从列表中剔除,但是此时微服务是正常的,可以提供服务的。由于客户端从Server无法获取到有效的微服务列表,因此导致业务故障。
为了解决在某些特殊情况下,比如网络大面积故障时,微服务不可用的问题,引入自我保护机制。
思想:宁可保留健康的和不健康的,也不盲目注销任何健康的服务。
这里肯定也带来了不好的地方,如果服务确实死掉了,但是依然保留在注册中心,那么会导致调用出错。
Eureka在CAP理论中是属于AP,也就是说当产生网络分区时,Eureka保证系统的可用性,但不保证系统里面数据的一致性。
二、配置
自我保护相关的配置有如下两个,默认enable-self-preservation是true,保持开启,只有enable-self-preservation是true,renewal-percent-threshold值才有意义,默认值是0.85。
#自我保护
#默认true
eureka.server.enable-self-preservation=true
#自我保护开启阈值
#默认0.85
eureka.server.renewal-percent-threshold=0.85
enable-self-preservation为false时,admin页面会出现一行文字,提示THE SELF PRESERVATION MODE IS TURNED OFF. THIS MAY NOT PROTECT INSTANCE EXPIRY IN CASE OF NETWORK/OTHER PROBLEMS.表示自我保护被关闭了。
一般我们在调测环境是关闭的,生产环境会开启。
三、自我保护触发
自我保护机制的触发条件:每分钟续约次数小于numberOfRenewsPerMinThreshold时,触发自我保护机制。
numberOfRenewsPerMinThreshold=期望的续约次数(expectedNumberOfRenewsPerMin)*续租百分比(eureka.server.renewal-percent-threshold);
期望的续约次数=当前注册的实例数*2,为什么乘以2,默认情况下,注册的实例每半分钟续约一次,那么一分钟续约2次,因此x2。
举例:服务实例数10个,期望每分钟续约10*2=20,期望阈值20*0.85=17,自我保护少于17时触发。
源码:
AbstractInstanceRegistry.class
public void evict(long additionalLeaseMs) {
logger.debug("Running the evict task");
if (!isLeaseExpirationEnabled()) {
logger.debug("DS: lease expiration is currently disabled.");
return;
}
此代码意思:if中判断为true,不走此逻辑,走下面的剔除。如果if为false。走此逻辑,不剔除。
PeerAwareInstanceRegistryImpl.class
public boolean isLeaseExpirationEnabled() {
if (!this.isSelfPreservationModeEnabled()) {
//如果打开自我保护,不进入此逻辑。
return true;
} else {
return this.numberOfRenewsPerMinThreshold > 0 && this.getNumOfRenewsInLastMin() > (long)this.numberOfRenewsPerMinThreshold;
}
}