一、问题背景

启动两个微服务,一个是Eureka server注册中心,另外一个是 Eureka client客户端

过了一段时间,打开注册中心网页时,界面上显示了红色粗体警告信息

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进入自我保护模式(SELF PRESERVATION MODE)。

什么叫自我保护模式?

我们知道,当微服务客户端启动后,会把自身信息注册到Eureka注册中心,以供其他微服务进行调用。一般情况下,当某个服务不可用时(一段时间内没有检测到心跳或者连接超时等),那么Eureka注册中心就会将该服务从可用服务列表中剔除,但是在微服务架构中,因为服务数量众多,可能存在跨机房或者跨区域的情况,因此当某个服务心跳探测失败并不能完全说明其无法正常提供服务而将其剔除,并且服务一旦剔除后,再重新注册将会重新进行负载均衡等等一系列的操作,考虑到性能问题,eureka会将不可用的服务暂时断开,并期望能够在接下来一段时间内接收到心跳信号,而不是直接剔除,同时,新来的请求将不会分发给暂停服务的实例,这就是eureka的保护机制,它保护了因网络等问题造成的短暂的服务不可用的实例,避免频繁注册服务对整个系统造成影响

进入自我保护模式的条件

条件:如果最近一分钟实际接收到的心跳值Renews除以期望的心跳阈值 Renews threshold小于等于0.85,即 Renews/Renews threshold≤0.85

Renews threshold:Eureka注册中心期望接收到的心跳值,计算方法:

  • 服务注册中心不注册自己: (1+2*n) 
  • 服务注册中心注册自己: (1+2*(n+1)) 

参数解析:

  • 数字1:这个是Eureka框架代码里面写时的最低阈值1,意味着没有任何客户端注册,阈值也有1
  • 数字2:这个是最近一分钟接收到的心跳次数,Eureka客户端和注册中心心跳检测默认是30s一次,那么一分钟就是2次,可以通过下面的参数进行调整
#定义每分钟发送到服务器的更新数 default is 30 也就是每30秒续订一次
eureka.instance.leaseRenewalIntervalInSeconds=30
  • 数字n:这个是客户端的数量个数,如果注册中心自己不注册,那么有几个客户端,n就是几,如果注册中心自己也要注册,那么就需要把注册中心也加上,这是因为在实际生产环境中,为了保证注册中心的高可用,往往注册中心会搭建集群,那么注册中心A,B,C相互之间也会注册,所以就相当于一个客户端。是否注册可以通过下面的代码进行设置
#是否在Eureka Server中注册默认是true
eureka.client.registerWithEureka=false

Renews :注册中心实际接收到的心跳值,计算方法:

  • 服务注册中心不注册自己: 2*n
  • 服务注册中心注册自己: 2*(n+1) 

参数解析

  • 数字2:这个是最近一分钟接收到的心跳次数,Eureka客户端和注册中心心跳检测默认是30s一次,那么一分钟就是2次,可以通过下面的参数进行调整(设置代码同上)
  • 数字n:这个是客户端的数量个数,如果注册中心自己不注册,那么有几个客户端,n就是几,如果注册中心自己也要注册,那么就需要把注册中心也加上,这是因为在实际生产环境中,为了保证注册中心的高可用,往往注册中心会搭建集群,那么注册中心A,B,C相互之间也会注册,所以就相当于一个客户端。是否注册可以通过下面的代码进行设置(设置代码同上)

0.85:这个参数是Eureka默认的一个比值参数,代表eureka-server最后一分钟收到的心跳次数小于等于总心跳次数的85%,可通过下面的代码进行调整

eureka.server.renewalPercentThreshold=0.85

因此,再回头查看报错提示:

因为一个注册中心,一个客户端,并且服务中心还没有自注册,所以renews=2,

Renews threshold=3,那么renews/Renews threshold=2/3=0.67<0.85

所以进入自我保护模式

三、处理方式

  • 在生产上可以开自注册,部署两个server 
  • 在本机器上测试的时候,可以把比值调低,比如0.49 
eureka.server.renewalPercentThreshold=0.49
  • 或者简单粗暴把自我保护模式关闭
# 默认值是true
eureka.server.enable-self-preservation=false

当关闭自我保护模式,会提示下面的信息

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

翻译

自我保护模式已关闭。 在网络/其他问题的情况下,这可能无法保护实例到期,意思就是可能提供不可用的服务给客户端调用

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐