Eureka界面EMERGENCY提示背后的保护机制

背景:
SpringCloud Eureka 投入使用很久了,server界面一直有红色提示:

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

在这里插入图片描述
这个虽然不影响使用,但背后体现的是Eureka保护机制,甚至可以延伸到分布式基础CAP理论,我们来研究下吧~


一、Eureka 保护机制

Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%eureka.server.renewal-percent-threshold = 0.85),如果低于 85%,就会触发 Eureka 的保护机制,Eureka Server 会将这些实例保护起来,让这些实例不会过期(即注册中心服务列表不会剔除该实例),但是在保护期内如果服务刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,此时会调用失败,对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等。

Web界面可以看到2个参数:
在这里插入图片描述
Renews threshold :Eureka Server 期望每分钟收到客户端实例续约的总数。
Renews (last min) :Eureka Server 最后 1 分钟收到客户端实例续约的总数


Renews threshold的计算公式:
    protected void updateRenewsPerMinThreshold() {
            this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfClientsSendingRenews
                    * (60.0 / serverConfig.getExpectedClientRenewalIntervalSeconds())
                    * serverConfig.getRenewalPercentThreshold());
        }

自我保护阀值 = 服务总数(包括自注册) * 每分钟续约数 * 自我保护续约百分比阀值因子eureka.server.renewal-percent-threshold:默认0.85)。

其中 每分钟续约数 =(60S/客户端续约间隔 lease-renewal-interval-in-seconds:默认30s


自我保护模式激活逻辑:

Eureka Server提供了一个EvictionTask定时(eviction-interval-timer-in-ms: 默认60s)清理续约超时的服务。清理之前首先判断是否需要清理(isLeaseExpirationEnabled())。

public boolean isLeaseExpirationEnabled() {
        if (!isSelfPreservationModeEnabled()) {
            // The self preservation mode is disabled, hence allowing the instances to expire.
            return true;
        }
        return numberOfRenewsPerMinThreshold > 0 && getNumOfRenewsInLastMin() > numberOfRenewsPerMinThreshold;

这个判断方法首先会判断是否开启了自我保护开关enable-self-preservation),如果开启了,则会继续判断上一分钟的续约数是否小于自我保护阀值,如果上一分钟的续约数(numOfRenewsInLastMin)小于自我保护阀值(numberOfRenewsPerMinThreshold),则开启自我保护机制,不再进行服务的剔除。


二、解决方法

解决方式一般有三种:

1.关闭自我保护模式

在server端配置:

# 关闭保护机制,默认为true
eureka.server.enable-self-preservation: false          			

# 清理无效节点的时间间隔,默认60s(注:如果不添加这个配置,即使eureka.instance.lease-expiration-duration-in-seconds配置时间很短,也不会马上剔除节点)
eureka.server.eviction-interval-timer-in-ms: 4000				

在client端配置:

# 定义服务失效时间,Eureka服务端收到最后一次心跳之后等待的时间上限,超过该时间之后服务端会将该服务实例从服务清单中剔除,从而禁止服务调用请求被发送到该实例上,单位:秒(默认90s)
lease-expiration-duration-in-seconds: 10

# 定义心跳间隔时间,Eureka客户端向服务端发送心跳的时间间隔,单位:秒(默认30s)
# 注意:这种调高频率的操作只适用于实例较少的Eureka集群,因为会增加集群通信压力
lease-renewal-interval-in-seconds: 5

2.降低renewalPercentThreshold的比例
eureka.server.renewal-percent-threshold比例降低到默认值0.85以下,比如0.4

3.部署多个 Eureka Server 并开启其客户端注册
eureka.client.register-with-eureka不要设为false,默认为true(待测试)

个人建议:测试环境可以关闭保护模式,生产环境最好打开保护模式,部署多个 Eureka Server并开启client注册

Eureka 的自我保护模式是有意义的,该模式被激活后,它不会从注册列表中剔除因长时间没收到心跳导致租期过期的服务,而是等待修复,直到心跳恢复正常之后,它自动退出自我保护模式。这种模式旨在避免因网络分区故障导致服务不可用的问题。

例如,两个客户端实例 C1 和 C2 的连通性是良好的,但是由于网络故障,C2 未能及时向 Eureka 发送心跳续约,这时候 Eureka 不能简单的将 C2 从注册表中剔除。因为如果剔除了,C1 就无法从 Eureka 服务器中获取 C2 注册的服务,但是这时候 C2 服务是可用的。


三、扩展:CAP理论

CAP理论,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼

一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)

可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)

分区容忍性(P):大多数分布式系统都分布在多个子网络。每个子网络就叫做一个区(partition)。分区容错的意思是,区间通信可能失败。比如,一台服务器放在中国,另一台服务器放在美国,这就是两个区,它们之间可能无法通信;

一般来说,分区容错无法避免,因此可以认为 CAP 的 P 总是成立。CAP 定理告诉我们,剩下的 C 和 A 无法同时做到
在这里插入图片描述

在分布式系统的设计中,没有一种设计可以同时满足一致性,可用性,分区容错性 3个特性;
注意:不要将 弱一致性最终一致性 放到CAP理论里混为一谈

那么我们对这三者如何权衡?

牺牲分区容错性 (CA)

作为分布式系统,分区必然总会发生(2年1次50分钟还是1年3次共10分钟?),因此认为CAP的讨论是大部分建立在P确立前提下。假设我们牺牲了P这个时候因为网络故障发生了分区导致节点不可用,这个时候请求响应了error、timeout,与可用性的定义相冲突了。

但是,我们又假如分区大部分时间是不存在的,这时对单节点的读\写,那么就无需作出C、A的取舍。但是上面说分区总会发生这不互相矛盾么,还是取舍。假如1年时间内99.99%时间是正常的,不可用时间为0.01%(52.56分钟)不可用,若这个时间属于业务接受范围,或者只在某个地区(华南、华北、华中?)有影响,那么CA也是可以选择的。

牺牲可用性 (PC)

最典型的案例是RDBMS集群Redis集群,这两种都是利用主从复制实现读写分离的方案。假如两者都是建立一主多从的集群,在主节点写入数据,为了保证随后的读操作获取最新数据(一致性),这个读操作仍会请求主节点(读写分离的复杂点在从库同步不及时导致业务的异常,为了保证业务的正常性写后的读会请求主库),某个从节点挂了但是只要主节点和其他从节点仍然正常运作,就满足分区容错性。但是哪天主节点因为网络故障导致写操作的error或者timeout,那么这个系统就不可用了(牺牲可用性)。

这个时候可以引入其他功能和机制完成,例如Redis哨兵模式、故障转移功能。

牺牲一致性 (PA)

最典型的案例是Cassanda集群Riak集群,这种类型的分布式数据库,可以任意节点写入,任意节点读取,当作为集群出现,无论写入哪个节点,都将会把该节点的数据同步到其他节点上,因为这种同步方式,读取数据时只要访问一个节点就足够了(喜欢任意访问也不拦着你),但是因为其他节点数据同步原因,数据可能并不是最新的(牺牲一致性)。如果当前节点因为网络异常导致分区变得不可用(无论读\写),可以转移访问节点(可用性)。

另外这里说的牺牲一致性,并不代表放弃一致性,而PA选择的是最终一致性(系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态)

Eureka在CAP理论当中是属于PA , 根据前面研究的保护机制,当产生网络分区时,Eureka保证系统的可用性,但不保证系统里面数据的一致性, 举个例子。当发生网络分区的时候,Eureka-Server和client端的通信被终止,server端收不到大部分的client的续约,这个时候,如果直接将没有收到心跳的client端自动剔除,那么会将可用的client端剔除,这不符合AP理论,所以Eureka宁可保留也许已经宕机了的client端 , 也不愿意将可以用的client端一起剔除。 从这一点上,也就保证了Eureka程序的健壮性,符合AP理论


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值