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


这篇博文总结下当使用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参考资料

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐