之前我说明了Eureka注册中心的保护模式,由于在该模式下不能剔除失效节点,故按原有配置在实际中不剔除总感觉不是太好,所以深入研究了一下。当然,这里重申一下,不管实例是否有效剔除,消费端实现Ribbon重试机制也是必须的。

说下背景,在微服务架构中,有个CAP原则(一致性,可用性,分区容错性),三者由于存在互斥,只能同时满足其二,第三点需要有一定舍弃。Eureka舍弃了强一致性,所以在进入保护模式后,失效节点的一致性不能得到保证。

以下是我验证后的几种方式,可以实现服务的及时剔除。

1、关闭自我保护模式eureka.server.enable-self-preservation=false来关闭。但是,这种方式有违eureka的CAP原则,所以,我并不推荐这种方式。

2、在说明之前,我们先看下源码。

以下代码判断是否进入刷新服务列表的步骤。该代码在AbstractInstanceRegistry.java和PeerAwareInstanceRegistryImpl.java中。

public void evict(long additionalLeaseMs) {
logger.debug("Running the evict task");
//主要是看isLeaseExpirationEnabled返回值
if (!isLeaseExpirationEnabled()) {
logger.debug("DS: lease expiration is currently disabled.");
return;
}
//进入筛选过期实例的方法。这里省略
}
public boolean isLeaseExpirationEnabled() {
//isSelfPreservationModeEnabled由是否开启保护模式配置决定,默认为true
if (!isSelfPreservationModeEnabled()) {
return true;
}
return numberOfRenewsPerMinThreshold > 0 && getNumOfRenewsInLastMin() > numberOfRenewsPerMinThreshold;
}

主要看numberOfRenewsPerMinThreshold和getNumOfRenewsInLastMin()方法。我们主要看numberOfRenewsPerMinThreshold初始化的地方。getNumOfRenewsInLastMin()方法是统计最后一分钟内的心跳统计总数。

//PeerAwareInstanceRegistryImpl.java
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {
// Renewals happen every 30 seconds and for a minute it should be a factor of 2.
this.expectedNumberOfRenewsPerMin = count * 2;
this.numberOfRenewsPerMinThreshold =
(int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());
//....
}

count是注册在注册中心的实例总数,包括高可用的另外注册中心。我们可以看到,这里是以硬编码的方式初始化expectedNumberOfRenewsPerMin,通过 实例数*2。为什么*2,因为实例默认发送心跳时间是30s,所以通过*2统计一分钟类应收到的总的心跳次数,因为是硬编码,所以不建议修改实例端心跳周期时间!。numberOfRenewsPerMinThreshold是通过总的心跳数乘以允许失败的比例。默认为0.85。expectedNumberOfRenewsPerMin在默认情况下,会每隔15分钟刷新一次。

通过上面分析,我们大致了解了不通过关闭自我保护模式下触发服务剔除操作的条件。得出以下两种方案来实现失效节点的剔除(亲测有效)。

  1. 通过修改每分钟心跳成功最低比例来控制注册中心不进入自我保护模式,实时剔除节点(需要等到实例定义的过期时间,且注册中心触发刷新周期)。eureka.server.renewal-percent-threshold来配置比例。举个例子,当前我们有4个服务实例,计算所知,每分钟有4*2=8个心跳,当需要实现一个实例意外掉线后,则每分钟实际收到心跳为6个,8*x<6时不会进入保护模式,则x<0.75,配置为0.75以下大致可以实现剔除操作,但是由于网络不稳定因素,存在心跳异常,所以该值尽量设置小于0.75多点,如0.5。为什么默认会0.85呢,我觉得应该是有算法支撑,但从结果来看,保护模式还是适用于大规模的服务集群,当一台或几台挂掉之后,也不会进入保护模式,默认比例下,可以实现实例的剔除。如果集群较小,如2台,挂掉一台就会进入保护模式,且保护模式意义不大,可以关闭自我保护模式。
  2. 通过设置实例的心跳时间,改为较小的周期。由于需要判断每分钟实际心跳数>实例总数*2*0.85,才不会进入自我保护模式,所以设置心跳周期较小,使实际心跳数多于比例下的心跳数,可以实现实例的及时剔除。实例的心跳周期设置:eureka.instance.lease-renewal-interval-in-seconds,如设置为5等等,具体可根据以上算法来计算合适的值。

Spring Cloud Eureka的自我保护模式与实例下线剔除的更多相关文章

  1. Spring Cloud Eureka 自我保护机制

    Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来,让这些实例不会过期,但是在保护期内如果 ...

  2. Spring Cloud Eureka 自我保护机制实战分析

    前些天栈长在Java技术栈微信公众号分享过 Spring Cloud Eureka 的系列文章: Spring Cloud Eureka 自我保护机制 Spring Cloud Eureka 常用配置 ...

  3. spring cloud Eureka常见问题总结

    Spring Cloud中,Eureka常见问题总结. 指定Eureka的Environment 1 eureka.environment: 指定环境 参考文档:https://github.com/ ...

  4. 第三章 服务治理:Spring Cloud Eureka

    Spring Cloud Eureka是Spring Cloud Netflix 微服务套件中的一部分,它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能.Spri ...

  5. 【SpringCloud微服务实战学习系列】服务治理Spring Cloud Eureka

    Spring Cloud Eureka是Spring Cloud Netflix微服务中的一部分,它基于NetFlix Sureka做了二次封装,主要负责完成微服务架构中的服务治理功能. 一.服务治理 ...

  6. Eureka的自我保护模式

    一 Eureka的自我保护模式 进入自我保护模式最直观的体现就是Eureka Server首页的警告,如下图: 默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,E ...

  7. 服务治理-> Spring Cloud Eureka

    服务治理->搭建服务注册中心 服务治理可以说是微服务架构中最为核心和基础的模块, 它主要用来实现各个微服务 实例的自动化注册与发现. 为什么我们在微服务架构中那么需要服务治理模块呢?微服务 系统 ...

  8. SpringCloud系列六:Eureka的自我保护模式、IP选择、健康检查

    1. 回顾 前面讲了很多Eureka的用法,比如Eureka Server.Eureka Server的高可用.Eureka Server的用户认证(虽然未完全实现).元数据等, 这章将讲解剩下的自我 ...

  9. Spring Cloud Eureka 服务注册中心(二)

    序言 Eureka 是 Netflix 开发的,一个基于 REST 服务的,服务注册与发现的组件 它主要包括两个组件:Eureka Server 和 Eureka Client Eureka Clie ...

随机推荐

  1. 将Docker容器转移至另一服务器

    1 把当前的容器提交为一个镜像: docker commit 容器名 镜像名 2 将镜像存为tar文件 docker save 镜像名 >备份文件.tar 3将 备份文件.tar 复制到目的主机 ...

  2. [Linux] 纯净ubuntu快速搭建宝塔面板

    宝塔官方建议是纯净的系统,我使用docker运行一个ubuntu容器,模拟一个纯净的系统,这样也不会影响到我的其他服务. docker run --name baota -id -p 8888:888 ...

  3. linux 安装PostgreSQL12

    一.安装步骤 1.设置保存安装包的目录 # cd /usr/local/src 2.开始下载源包 # wget https://ftp.postgresql.org/pub/source/v12.1/ ...

  4. react相关小技巧

    一.我们在项目中切换路由的时候可能会遇到 Warning: setState(...): Can only update a mounted or mounting component. This u ...

  5. -shared -fPIC

    gcc -shared -fPIC -o 1.so 1.c   这里有一个-fPIC参数 PIC就是position independent code PIC使.so文件的代码段变为真正意义上的共享

  6. c# WF 第3节 窗体的属性

    本节内容: 1:如何找到窗口属性 2:窗口属性 1:如何找到窗口属性 2:窗口属性

  7. 201871010116-祁英红《面向对象程序设计(java)》第6-7周学习总结

    项目 内容 <面向对象程序设计(java)> https://home.cnblogs.com/u/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.c ...

  8. conda基础命令

    1.首先在所在系统中安装Anaconda.可以打开命令行输入conda -V检验是否安装以及当前conda的版本. 2.conda常用的命令. 1)conda list 查看安装了哪些包. 2)con ...

  9. 矩阵快速幂之Kiki & Little Kiki 2

    题意是:给出一串01串,每一秒,每个位置得灯会根据左边那个灯得状态进行改变,(第一个得左边为最后一个)如果左边为1,那么自己就会改变状态,左边为0则不用,问n秒改01串的状态 ///// 首先,我们发 ...

  10. Vue 中的 子组件 给 父组件 传值

    子组件的某一个事件(sendData)内部,通过this.$emit('事件名', 传递的值)传递数据父组件在调用子组件的地方,绑定了子组件自定义的 事件名(change-data) 定义父组件的地方 ...