【源码】eureka 如何开启自我保护机制?

1. 背景

       我们都知道自我保护机制,都知道15分钟,85%的心跳阈值,那么这是如何计算的?源码中怎么体现的呢?今天来研究一下~



2.进入自我保护的模式的判断

public boolean isLeaseExpirationEnabled() {
		// eureka server自我保护功能是否已经过期
    if (!isSelfPreservationModeEnabled()) {
        // The self preservation mode is disabled, hence allowing the instances to expire.
        // 自我保护模式关闭的情况下,心跳过期功能是一直能够使用的
        return true;
    }
    // 当自我保护模式功能开启时,看看上一分钟发送的心跳数是否大于numberOfRenewsPerMinThreshold
    // numberOfRenewsPerMinThreshold 就是至少应该发送这么多心跳次数,eureka server才算正常,才不会进入保护模式
    // 上一分钟发送心跳次数是否大于进入自我保护的阈值
    return numberOfRenewsPerMinThreshold > 0 && getNumOfRenewsInLastMin() > numberOfRenewsPerMinThreshold;
}

       上面这个方法就是eureka 判断是否进入自我保护模式的方法,核心就是getNumOfRenewsInLastMin() > numberOfRenewsPerMinThreshold 如果上一分钟收到的心跳数getNumOfRenewsInLastMin小于 每分钟应该收到的最小心跳数numberOfRenewsPerMinThreshold ,那么就进入自我保护模式。
       这个时候,基于心跳的自动踢出定时任务就失效了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OnAecXKu-1622100307706)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c3710dd0-97f9-46d0-b6e8-7ba11673a7da/Untitled.png)]



3.计算粗糙的核心数据expectedNumberOfRenewsPerMin与numberOfRenewsPerMinThreshold

expectedNumberOfRenewsPerMin: 每分钟应该收到的心跳数

numberOfRenewsPerMinThreshold:每分钟应该收到的最少心跳数

       这两个数据是自我保护模式判断的核心。但是eureka关于这两个数据的计算比较粗糙,而且散落在代码的各地。

总共有两个地方对这个数据执行了初始化:

1.com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#openForTraffic 在eureka server初始化完成时,这个时候已经从其他eureka server 拉取到注册表。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bd7zdBce-1622100307709)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/abfd9dcc-7e14-415c-8cf6-094334810980/Untitled.png)]
2. com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#updateRenewalThreshold 开启了定时任务,默认每15分钟执行一次。首次启动延迟15分钟执行(因为在openForTraffic中已经初始化过了

获取注册表中的数据
Applications apps = eurekaClient.getApplications();
int count = 0;
for (Application app : apps.getRegisteredApplications()) {
    for (InstanceInfo instance : app.getInstances()) {
        // 非亚马逊云的都注册了
        if (this.isRegisterable(instance)) {
            ++count;
        }
    }
}
// 这里的计算就比较粗糙 使用的是默认心跳30秒,那么每分钟默认心跳数是2,那么每分钟期待的就是注册数*2
this.expectedNumberOfRenewsPerMin = count * 2;
// 0.85 * expectedNumberOfRenewsPerMin
// 上面都计算出来,这里还又计算了一遍,这里默认设定的阈值比例为0.85
this.numberOfRenewsPerMinThreshold = (int) ((count * 2) * serverConfig.getRenewalPercentThreshold());

       那么这两个数据是只在这计算一次吗?

       其实并不是,这里是每15分钟会计算一次的,这里的计算结果还会会在其他的行为中进行增删改查。

       我们需要知道的是,自我保护机制是应对的网络故障,或客户端非自然下线的情况。 主要是针对于心跳检查。那么在这15分钟的计算周期内,如果出现注册register,自主下线cancel 这种自主的行为还是不会受到自我保护机制的影响的,该上线上线,该下线下线。

注册register

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HhrMH2dK-1622100307711)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/eef0f9ad-cd60-4c2a-bd3a-3474c819b8e9/Untitled.png)]

下线cancel

方法:com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#cancel

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LiDHeV2D-1622100307714)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/23af5178-a87c-47bb-9151-9eb08e7382c4/Untitled.png)]



4.15分钟的由来

private void scheduleRenewalThresholdUpdateTask() {
    timer.schedule(new TimerTask() {
                       @Override
                       public void run() {
                           updateRenewalThreshold();
                       }
                   }, serverConfig.getRenewalThresholdUpdateIntervalMs(),//启动后延迟15分钟后开始执行updateRenewalThreshold线程任务
            serverConfig.getRenewalThresholdUpdateIntervalMs());// 每15分钟执行一次
}

上面就是15分钟的由来,可以通过getRenewalThresholdUpdateIntervalMs 来进行设置

这个是在DefaultEurekaServerContext初始化时开启了该定时任务

具体调用链路:

com.netflix.eureka.DefaultEurekaServerContext#initializecom.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#initcom.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#scheduleRenewalThresholdUpdateTask



5.最后一分钟统计数据的由来

       这个统计我想应该来自于eureka server 接收 eureka client 心跳时进行统计的。

       在第一点中有关于进入保护模式的判断,getNumOfRenewsInLastMin() 就是获取上一分钟接收的心跳数。

       这个由什么来进行统计的呢?是由com.netflix.eureka.registry.AbstractInstanceRegistry#renewsLastMin来处理的,这是在创建PeerAwareInstanceRegistryImpl对象时启动的,设定的时长是1分钟重置一次。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7R2f6AUH-1622100307715)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/acac165d-e06c-4c7f-b480-af191150926b/Untitled.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ZXo7RhW-1622100307717)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/5a71b302-ee97-4da2-888f-4e912fed819e/Untitled.png)]

       什么时候新增的呢?

       在发送心跳续约信息时处理的

com.netflix.eureka.registry.AbstractInstanceRegistry#renew

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uI8maljO-1622100307733)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/5045873e-0d9b-4171-8716-78d9618fdfb7/Untitled.png)]



6. 自我保护何时解除

       自我保护机制是动态判断的,只要renewsLastMin统计的数量大于numberOfRenewsPerMinThreshold就自动解除了自我保护机制了



7.自我保护机制优缺点

自我保护好处:

       防止网络波动情况下,大面积服务下线导致服务瘫痪。这个网络波动主要是指的eureka client 与eureka server 或者 eureka server 与 eureka server之间。 这样可以让客户端使用自己的本地缓存继续进行服务。

自我保护的坏处:

       不规范的kill服务,还有0.85这个值,其实都会造成真正的服务下线了,但是无法被剔除。是否是网络波动其实不好判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欢谷悠扬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值