当使用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.
翻译成中文就是:
自我保护模式已关闭。 在网络/其他问题的情况下,这可能无法保护实例到期。
这到底是什么意思呢?
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
服务注册中心不注册自己: 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服务器获得可用的注册服务。 因此,这是“自我保存模式”的目的
- 最好将其打开
registerWithEureka: false
防止它注册到其他服务器上,为什么它会显示在阈值计数中?
- 最小阈值1 是代码中写死的,
registerWithEureka
设置为false,因此将没有Eureka实例寄存器,阈值为1。- 在生产环境中,通常我们部署两个Eureka服务器,并将
registerWithEureka
设置为true。- 因此,阈值将为2,Eureka服务器将向其自身续租两次(每分钟两次),因此续订不超过阈值将不会有问题。
# 定义每分钟发送到服务器的更新数 default is 30 也就是每30秒续订一次
eureka.instance.leaseRenewalIntervalInSeconds=30
# default is 0.85
eureka.server.renewalPercentThreshold=0.85
renew threshold 5
rewnews last min: (client1) 2 + (client2) 2 -> 4
根据公式计算阀值:2*(2+1)*0.85= 5.1
只取整数部分5
是的,这很正常,因为阈值初始值设置为1。因此,如果registerWithEureka设置为false,则续订始终低于阈值。
- 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.