admin管理员组

文章数量:1577493

Eureka服务注册中心搭建好后页面有个错误信息怎么办?

    • 1.1 问题背景
    • 1.2 问题分析整理
    • 1.3 解决方案
    • 1.4参考资料

这篇博文总结下当使用Eureka 服务注册中心时页面可能出现的两个错误提示信息。

1.1 问题背景

当使用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可能会不正确地提出索赔要求。 续订比阈值要少,因此仅出于安全性考虑,实例不会过期。

有人说,在Eureka Server 服务注册中心的配置文件中将这个属性设置成false 就行了。

# 默认值是true
eureka.server.enable-self-preservation=false

但是当你修改成false 后会发现那个错误信息是消失了,但是却变成了这个新的错误信息

THE SELF PRESERVATION MODE IS TURNED OFF. THIS MAY NOT PROTECT INSTANCE EXPIRY IN CASE OF NETWORK/OTHER PROBLEMS.

翻译成中文就是:

自我保护模式已关闭。 在网络/其他问题的情况下,这可能无法保护实例到期。

这到底是什么意思呢?

1.2 问题分析整理

eureka.server.enable-self-preservation

解决上面问题的关键在于理解这个自我保护机制是什么意思?

  • 确保您已访问此页面以了解有关Eureka群集配置的信息。
  • Eureka客户端尝试与同一区域中的Eureka Server通信。如果在与服务器通信时遇到问题,或者该服务器不存在于同一区域中,则客户端将故障转移到其他区域中的服务器。
  • 服务器开始接收流量后,在服务器上执行的所有操作都将复制到服务器知道的所有对等节点。如果某个操作由于某种原因失败,那么该信息将在下一个检测信号上进行协调,该检测信号也会在服务器之间复制。
  • 当Eureka服务器启动时,它将尝试从相邻节点获取所有实例注册表信息。如果从节点获取信息有问题,则服务器会在放弃之前尝试所有对等节点。如果服务器能够成功获取所有实例,则它将基于该信息设置应接收的续订阈值。如果有任何时间,续订降到为此值配置的百分比以下(15分钟内低于85%),服务器将停止实例过期以保护当前实例注册表信息。
  • 在Netflix中,以上保护措施称为自我保护模式,主要用于在一组客户端和Eureka Server之间存在网络分区的情况下的保护措施。在这些情况下,服务器尝试保护它已经拥有的信息。在大规模中断的情况下,可能存在一些场景,这可能会导致客户端获取不再存在的实例。客户端必须确保它们对eureka服务器具有弹性,可以返回不存在或无响应的实例。在这些情况下,最好的保护是快速超时并尝试其他服务器。
  • 在这种情况下,如果服务器无法从相邻节点获取注册表信息,它将等待几分钟(5分钟),以便客户端可以注册其信息。服务器通过将流量仅偏向一组实例并导致容量问题,努力不向客户端提供部分信息。
  • Eureka服务器使用此处所述的Eureka客户端与服务器之间使用的相同机制相互通信。
  • 另外值得注意的是,可以在服务器上调整多种配置,包括在需要时进行服务器之间的通信。
    对等之间的网络中断期间会发生什么?
  • 如果对等点之间发生网络中断,则可能发生以下情况
    • 对等方之间的心跳复制可能会失败,并且服务器会检测到这种情况,并进入保护当前状态的自保留模式。
    • 注册可能发生在孤立的服务器上,某些客户端可能会反映新的注册,而其他客户端则可能没有。
    • 网络连接恢复到稳定状态后,情况会自动更正。当对等方能够正常通信时,注册信息会自动传输到不具有它们的服务器。
  • 最重要的是,在网络中断期间,服务器会尝试尽可能地具有弹性,但是在此期间,客户端可能会对服务器有不同的看法。
    我们知道Eureka 是一个服务治理框架,支持服务注册和服务发现。

也就是说,每个微服务实例都需要以每30秒一次的频率将自己注册的有效期限续签到Eureka Server.

这个时间间隔可以通过如下参数进行调整

#default second is 30
eureka.instance.leaseRenewalIntervalInSeconds=30
  • Renews (last min):表示最近一分钟从Eureka 实例收到的续订次数
  • Renews threshold:续订阀值,Eureka服务器期望每分钟从Eureka实例收到的续订阀值,初始化值最低为1 (次)

服务注册中心不注册自己: 2*(n+1)*0.85 只取整数部分

服务注册中心注册自己: 2*n*0.85 只取整数部分
如下图所示:

  • 如果registerWithEureka 设置成false,eureka.instance.leaseRenewalIntervalInSeconds 设置成30
  • 然后运行两个微服务实例,两个微服务实例将会每分钟发送4个续订,即Renews (last min):4
  • Eureka Server 最小的阀值是1, 所以阀值是5(此数字将乘以一个因子eureka.server.renewalPercentThreshold,将在后面讨论)

根据公式计算阀值:2*(2+1)*0.85= 5.1 只取整数部分5

SELF PRESERVATION MODE: if Renews (last min) 小于等于 Renews threshold, SELF PRESERVATION MODE(自我保护模式)将会被激活

因此在上例中,由于阈值为5,所以激活了SELF PRESERVATION MODE(自我保护模式),但是Eureka服务器每分钟只能接收4次更新。

  • 问题一:自我保护机制的目的是什么?文档中说客户端可以获取不存在的实例?建议打开还是关闭
  • SELF PRESERVATION MODE(自我保护模式)”旨在避免不良的网络连接失败。
  • Eureka实例A和B之间的连通性很好,但是B由于连接中断而未能在短时间内将其租约续签到Eureka服务器,此时Eureka服务器不能简单地将实例B踢出去。 尽管B可用,但A不会从Eureka服务器获得可用的注册服务。 因此,这是“自我保存模式”的目的
  • 最好将其打开
  • 问题二:我有一个单一的Eureka 服务器然后配置了 registerWithEureka: false 防止它注册到其他服务器上,为什么它会显示在阈值计数中?
  • 最小阈值1 是代码中写死的, registerWithEureka设置为false,因此将没有Eureka实例寄存器,阈值为1。
  • 在生产环境中,通常我们部署两个Eureka服务器,并将registerWithEureka设置为true。
  • 因此,阈值将为2,Eureka服务器将向其自身续租两次(每分钟两次),因此续订不超过阈值将不会有问题。
  • 问题三:对于我启动的每个客户,阈值计数都增加+2。 我猜是因为他们每分钟发送2条更新消息,对吗?
# 定义每分钟发送到服务器的更新数 default is 30 也就是每30秒续订一次
eureka.instance.leaseRenewalIntervalInSeconds=30
# default is 0.85 
eureka.server.renewalPercentThreshold=0.85
  • 问题四:Eureka服务器从不发送续订,而最后一分钟续订始终低于阈值。 这正常吗?
renew threshold 5
rewnews last min: (client1) 2 + (client2) 2 -> 4

根据公式计算阀值:2*(2+1)*0.85= 5.1 只取整数部分5

是的,这很正常,因为阈值初始值设置为1。因此,如果registerWithEureka设置为false,则续订始终低于阈值。

1.3 解决方案

  • Renews (last min):表示最近一分钟从Eureka 实例收到的续订次数
  • Renews threshold:续订阀值,Eureka服务器期望每分钟从Eureka实例收到的续订阀值,初始化值最低为1

if Renews (last min) 小于等于Renews threshold, SELF PRESERVATION MODE(自我保护模式)将会被激活

自我保护模式的意义何在?

试想一种场景,当一个客户端,通过API Gateway 调用微服务A,如果微服务A宕机不可用,那么如果API Gateway如果仍旧不断向A发出请求,那么很快API Gateway 资源(比如线程)就会耗尽。当然我们可以使用服务熔断技术,这样可以解决这个问题,但是仍旧有一个问题就是如何判断这个微服务已经宕机了?是强检测还是包容检测?

我们知道Eureka 是一个服务注册中心,它的自我保护开启和关闭的区别其实在于:

  • 如果自我保护开始,也就是说当 eureka.server.enable-self-preservation=true 时候,Eureka 将会相对来说比较包容微服务和服务注册中心之间的弱网络情况(网络不稳有波动),比如等待90秒后,如果还未注册上,就将其从服务注册中心剔除。
  • 如果自我保护关闭,也就是说当eureka.server.enable-self-preservation=false时候,Eureka 将会一旦有微服务在规定时间内没续期成功就直接将其从列表移除,这样其实有些过于暴力,除非微服务和服务注册中心能确保长期处于带宽网络良好情况,否则网络一旦有波动就将微服务实例从列表剔除

对于出现的错误提示信息,可以修改Eureka 服务注册中心的配置文件如下所示进行修复:

# 默认值是true
eureka.server.enable-self-preservation=true
# default is 30
eureka.instance.leaseRenewalIntervalInSeconds=30
# default is 0.85 we can set the value to 0.49
eureka.server.renewalPercentThreshold=0.49

参数修改后重启,需要等待至少一分钟后方可看到效果。

n 表示注册到服务注册中心到微服务个数

  • 如果服务注册中心不注册自身,
    • 阀值计算公式:2*(n+1)*0.85 结果只取整数部分
  • 如果服务注册中心注册自身
    • 阀值计算公式:2*n*0.85 结果只取整数部分

如果n 等于3 ,不注册自身,按照默认值计算阀值

  • 2*(3+1)*0.85= 6.8 -> 6 == 实际每分钟续订次数 6 = 2*3

  • 2*(3+1)*0.49= 3.92 -> 3 < 实际每分钟续订次数 6 = 2*3

这也是为什么修改那个参数为0.49 就可以解决这个问题的原因。

解决上述问题的更好的建议是:

  • 如果生产环境最好部署至少两台服务注册中心,然后开启自注册,当一个服务注册中心不稳时候快速切换其他服务注册中心,实现高可用的目的。
  • 续订降到为此值配置的百分比以下(15分钟内低于85%),服务器将停止实例过期以保护当前实例注册表信息,如果觉得有必要也可以调整阀值检测比例为0.49.

1.4参考资料

  • Eureka never unregisters a service
  • EurekaServer: wrongly claims self preservation is turned off when renewal threshold is low
  • Understanding Spring Cloud Eureka Server self preservation and renew threshold
  • Understanding Eureka Peer to Peer Communication
  • Spring Cloud Netflix Eureka - The Hidden Manual

本文标签: eurekaEmergencyincorrectlyinstancesCLAIMING