Spring Cloud Eureka 自我保护机制

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

我们在单机测试的时候很容易满足心跳失败比例在 15 分钟之内低于 85%,这个时候就会触发 Eureka 的保护机制,一旦开启了保护机制,则服务注册中心维护的服务实例就不是那么准确了,此时我们可以使用 eureka.server.enable-self-preservation=false来关闭保护机制,这样可以确保注册中心中不可用的实例被及时的剔除( 不推荐)。

自我保护模式被激活的条件是:在 1 分钟后, Renews (last min) < Renews threshold

这两个参数的意思:

  • Renews thresholdEureka Server 期望每分钟收到客户端实例续约的总数
  • Renews (last min)Eureka Server 最后 1 分钟收到客户端实例续约的总数

具体的值,我们可以在 Eureka Server 界面可以看到:

Spring Cloud Eureka 自我保护机制

可以看到,我们部署了 3 个 Eureka Server(自注册模式),另外,又部署 7 个服务,注册到 Eureka Server 集群,参数值分别为:

  • Renews threshold:17
  • Renews (last min):20

下面说下 Renews thresholdRenews threshold具体计算方式。

Renews threshold 计算代码:

this.expectedNumberOfRenewsPerMin = count * 2;
this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());

count表示服务的数量,如果 Eureka Server 开启自注册模式,也算一个服务,比如我们上面的示例, count的值就是 10(3 个自注册服务 + 7 个独立服务), serverConfig.getRenewalPercentThreshold()默认是 0.85(可以通过 eureka.server.renewal-percent-threshold配置)。

所以,根据上面的分析,我们可以计算出 Renews threshold的值: (int)(10 * 2 * 0.85) = (int)17 = 17

Renews (last min)计算方式: count * 2,数值 2 表示每 30 秒 1 个心跳,每分钟 2 个心跳的固定频率因子,所以具体值为: 10 * 2 = 20

如果在 1 分钟后, Renews (last min) < Renews threshold,默认需等待 5 分钟(可以通过 eureka.server.wait-time-in-ms-when-sync-empty配置),即 5 分钟后你会看到下面的提示信息:

Spring Cloud Eureka 自我保护机制
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.server.enable-self-preservation设为 false), 不推荐
  • 降低 renewalPercentThreshold的比例( eureka.server.renewal-percent-threshold设置为 0.5以下,比如 0.49), 不推荐
  • 部署多个 Eureka Server 并开启其客户端行为( eureka.client.register-with-eureka不要设为 false,默认为 true), 推荐

Eureka 的自我保护模式是有意义的,该模式被激活后,它不会从注册列表中剔除因长时间没收到心跳导致租期过期的服务,而是等待修复,直到心跳恢复正常之后,它自动退出自我保护模式。这种模式旨在避免因网络分区故障导致服务不可用的问题。例如,两个客户端实例 C1 和 C2 的连通性是良好的,但是由于网络故障,C2 未能及时向 Eureka 发送心跳续约,这时候 Eureka 不能简单的将 C2 从注册表中剔除。因为如果剔除了,C1 就无法从 Eureka 服务器中获取 C2 注册的服务,但是这时候 C2 服务是可用的。

所以,Eureka 的自我保护模式最好还是开启它。

Eureka Server 单机版配置示例:

debug: true
spring:
  application:
    name: eureka-server
logging:
  level:
    com.netflix.eureka: 'off'
    com.netflix.discovery: 'off'
server:
  port: 8100
eureka:
  instance:
    hostname: localhost
  server:
    enable-self-preservation: false #关闭自我保护机制
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

参考资料:

Original: https://www.cnblogs.com/xishuai/p/spring-cloud-eureka-safe.html
Author: 田园里的蟋蟀
Title: Spring Cloud Eureka 自我保护机制

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/540607/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Tomcat源码分析(二)Bootstrap启动类分析

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年6月5日
    069
  • 如何高效的在博客园上编写MD格式的博客(插件pycnblog,推荐)

    如何高效的在博客园上编写MD格式的博客 想要找一个随时可以查看自己的学习笔记,将笔记放在博客园是一个很不错的选择,但博客园本身的后台写还是很不方便。写MD格式的文档我还是喜欢使用 …

    Java 2023年5月30日
    097
  • Java的jstack命令使用详解

    jstack命令简介 jstack(Java Virtual Machine Stack Trace)是JDK提供的一个可以生成Java虚拟机当前时刻的线程快照信息的命令行工具。线…

    Java 2023年6月7日
    079
  • Spring官网下载dist.zip的几种方法

    Spring官网改版后,很多项目的完整zip包下载链接已经隐掉了,虽然Spring旨在引导大家用更”高大上”的maven方式来管理所依赖的jar包,但是完全…

    Java 2023年5月30日
    069
  • Spring Bean 循环依赖

    创建 A 实例时需要 B,创建 B实例时需要 A。 测试环境:https://gitee.com/jhxxb/MySpringBoot/tree/master/Spring-Bas…

    Java 2023年5月30日
    074
  • java MongoDB查询(一)简单查询

    MongoDB的java驱动提供了查询的功能,查询条件也是bson对象,这篇就看下怎么进行简单的数据查询 1、数据结构 集合:firstCollection 数据内容: { &#8…

    Java 2023年6月7日
    085
  • Spring Security http标签的use-expressions=”true”属性

    如果声明为true,那么在access属性要用hasRole()这样写: 如果声明为false(默认),那么access直接就是 本文出自 无忧之路 – 博客园 Ori…

    Java 2023年5月30日
    073
  • 多线程笔记(一)

    1. sleep()方法和yield()方法 共同点:让当前线程释放cpu资源,让其他线程来运行 不同点:调用sleep()方法后,线程进入到 TIMED_WAITING状态,等待…

    Java 2023年6月8日
    084
  • Java学习-第一部分-第二阶段-第七节:泛型

    线程 笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html) 程序(program) 是为完成特定任务、用某种语言编写的…

    Java 2023年6月16日
    079
  • 如何正确的中断线程?你的姿势是否正确

    Java停止线程的逻辑(协同、通知) 在Java程序中,我们想要停止一个线程可以通过interrupt方法进行停止。但是当我们调用interrupt方法之后,它可能并不会立刻就会停…

    Java 2023年6月5日
    064
  • 引路蜂地图API:Gis.Location包定义

    本包定义了GPS接收器一个通用接口,并提供对NMEA 2.0数据的解码方法。在Java ME平台上对JSR179 进行了封装. Coordinates 定义地址经纬度坐标。 Loc…

    Java 2023年5月30日
    0101
  • Junit执行单元测试用例成功,mvn test却失败的解决方法

    Junit执行单元测试用例成功,mvn test却失败的解决方法(具体体现为使用的H2数据库中mock进去的数据在Junit执行的时候可以访问到,但是mvn test的时候数据库却…

    Java 2023年6月13日
    058
  • 并发编程之:线程

    大家好,我是小黑,一个在互联网苟且偷生的农民工。前段时间公司面试招人,发现好多小伙伴虽然已经有两三年的工作经验,但是对于一些Java基础的知识掌握的都不是很扎实,所以小黑决定开始跟…

    Java 2023年6月7日
    074
  • Python对字符数据进行清洗

    import re mystr = "hahaAAA哈哈綂123./!#鱫愛" str1 = ”.join(re.findall(‘[\u4e00-\u9fa…

    Java 2023年6月8日
    062
  • Spring(四)-声明式事务

    Spring-04 声明式事务 1、事务的定义 事务就是由 一组逻辑上紧密关联的 多个工作单元(数据库操作)而合并成一个整体,这些操作 要么都执行,要么都不执行。 2、事务的特性:…

    Java 2023年6月15日
    065
  • Cannot deserialize value of type `java.time.LocalDateTime` from String “2021-10-02 00:00:00”

    问题:在对象中使用LocalDateTime接收前端时间字符串时报了以下错误(已经加了@DateTimeFormat注解) Caused by: com.fasterxml.jac…

    Java 2023年6月7日
    0110
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球