Eureka自我保护模式和故障提供程序的快速删除
向Eureka Server注册提供程序服务实例时,将保持心跳连接,通知您Eureka Server仍活着。
Eureka Server在运行期间会统计所有Provider实例的心跳,如果失效比例在一段时间间隔内(如15分钟)低于阈值(如85%),Eureka Server就会将当前所有的Provider实例的注册信息保护起来,让这些实例不会过期。当Eureka Server运行在保护模式时会有一条警告信息:
"EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE
该警告信息的界面如图2-8所示。
图2-8 Eureka Server运行在保护模式
保护模式可能会导致一些问题。有时Provider服务实例会由于内存溢出、网络故障等原因不能正常运行,而处于保护模式的Eureka Server不一定会将其从服务列表中剔除出去,所以会导致客户端出现调用失败。为了使失效的Provider能够快速被剔除,可以停用Eureka Server的保护模式,然后启用客户端的健康状态检查。
首先,需要在Eureka Server注册中心增加两个配置项,分别是关闭自我保护和设置清理失效服务的时间间隔,具体如下:
server:
port: 7777
spring:
application:
name: eureka-server
eureka:
...
server:
enable-self-preservation: false #关闭自我保护,防止失效的服务被一直访问(默认为true)
eviction-interval-timer-in-ms: 10000 #清理失效服务的间隔时间(单位为毫秒,默认为10×1000毫秒,即10秒)
上述两个关键配置项的说明如下:
(1)
eureka.,将自我保护参数值设置为false,以确保注册中心Eureka停止自我保护,在心跳比例小于阈值(如85%)的情况下,能够将不可用的实例删除。
eureka.配置项的默认值为true。也就是说,在默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server就会认为该实例已经出现故障,进而注销该实例(默认为90秒)。当发生网络通信故障时,微服务与Eureka Server之间无法正常通信,以上行为就可能变得非常危险——因为微服务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过自我保护模式来解决这个问题——当Eureka Server节点在短时间内丢失过多客户端(可能发生了网络故障)时,这个节点就会进入自我保护模式。一旦进入该模式,Eureka Server就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动退出自我保护模式。
综上所述,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目注销任何健康的微服务。使用自我保护模式可以让Eureka集群更加健壮和稳定。
在网络环境好、通信延迟低的场景(如开发环境)中,建议关闭自我保护模式,因为自我保护模式会导致不健康的服务得不到及时的注销。
(2)
eureka.eviction-interval-timer-in-ms=10000,设置清理失效服务的间隔时间为10秒,如果Provider确实已经失效,就能确保快速被剔除,默认清理失效服务的时间间隔为60秒,这个失效服务的剔除周期是比较长的。
一个完整的单体服务注册中心Eureka Server的参考配置如下:
server:
port: 7777
spring:
application:
name: eureka-server
eureka:
client:
register-with-eureka: false #单机版部署,注册中心不向其他注册中心注册自己
fetch-registry: false #单机版部署,注册中心不进行Provider实例清单检索
service-url:
#在浏览器中打开 http://localhost:7777/
#服务注册中心的配置内容,指定服务注册中心的位置
defaultZone:
${SCAFFOLD_EUREKA_ZONE_HOSTS:http://localhost:7777/eureka/}
instance:
prefer-ip-address: true #访问路径可以显示IP地址
instance-id: ${}:${}
ip-address: ${}
server:
enable-self-preservation: false #关闭自我保护,防止失效的服务被一直访问 (默认是 true)
eviction-interval-timer-in-ms: 10000 #扫描失效服务的间隔时间(单位为毫秒,默认为10×1000毫秒,即10秒)以上为单机版的Eureka Server参考配置,生产环境一般会使用集群模式,甚至使用Nacos集群替代Eureka Server。无论是Eureka Server集群还是Nacos集群,它们的具体配置原理都比较简单,这里不再赘述。
为了快速剔除失效的Provider,除了在Eureka中进行合理的配置之外,还需要在Provider(EurekaClient)微服务端进行有效的配置,从而与Eureka注册中心相互配置。Provider微服务的主要选项包括开启健康状态检查和续约心跳,如下所示:
eureka:
client:
healthcheck:
enabled: true #开启客户端健康检查
instance:
lease-renewal-interval-in-seconds: 5 #续约(心跳)频率
lease-expiration-duration-in-seconds: 15 #租约有效期
以上配置中的3个关键选项说明如下:(1)
eureka.client.,此配置项在Client注册一个EurekaHealthCheckHandler实例,该处理器会将磁盘空间状态(DiskSpaceHealthIndicator)、Hystrix健康状态(HystrixHealthIndicator)等多个维度的健康指标通过心跳发送到Eureka Server。如果没有注册EurekaHealthCheckHandler,Provider实例的运行状况就由默认的HealthCheckHandler实例确定,只要应用程序正在运行,默认的HealthCheckHandler就始终发送UP状态到Eureka Server。
(2)
eureka.in,此配置项设置了Client续约(心跳)的时间间隔为5秒,该配置项的默认设置为30秒。
(3)
eureka.in,此配置项设置了租约的有效期为15秒,该配置项的默认设置为90秒。在租约时间内,如果Client未续约(心跳),那么Eureka服务器将剔除该服务。
默认的续约频率为30秒,默认的租约有效期为90秒,也就是说,在默认情况下,一个Provider实例有3次心跳重试机会。
这里需要注意的是:配置项
eureka.client.应该放在a文件中,而不应该放在boo文件中。如果该选项配置在boo文件中,就可能导致Provider实例在Eureka上的状态为UNKNOWN,如图2-9所示。
图2-9 Provider实例在Eureka上的状态为UNKNOWN
将Provider(如uaa-provider)的配置项
eureka.client.从boo文件移到a文件,然后重启该Provider的实例。之后可以看到Provider的实例(如uaa-provider的两个实例)在Eureka上的状态从UNKNOWN变成了UP,如图2-10所示。
图2-10 uaa-provider的两个实例在Eureka上的状态从UNKNOWN变成了UP
本文给大家讲解的内容是Eureka自我保护模式与失效Provider的快速剔除
- 下篇文章给大家讲解的是Eureka服务注册与发现:Config配置中心;
- 觉得文章不错的朋友可以转发此文关注小编;
- 感谢大家的支持!