标签:new news interval 筛选 服务 就会 可靠性 expect eureka
之前我说明了Eureka注册中心的保护模式,由于在该模式下不能剔除失效节点,故按原有配置在实际中不剔除总感觉不是太好,所以深入研究了一下。当然,这里重申一下,不管实例是否有效剔除,消费端实现Ribbon重试机制也是必须的。
说下背景,在微服务架构中,有个CAP原则(一致性,可用性,可靠性),三者由于存在互斥,只能同时满足其二,第三点需要有一定舍弃。Eureka舍弃了强一致性,所以在进入保护模式后,失效节点的一致性不能得到保证。
以下是我验证后的几种方式,可以实现服务的及时剔除。
1、关闭自我保护模式eureka.server.enable-self-preservation=false来关闭。但是,这种方式有违eureka的CAP原则,所以,我并不推荐这种方式。
2、在说明之前,我们先看下源码。
以下代码判断是否进入刷新服务列表的步骤。该代码在AbstractInstanceRegistry.java和PeerAwareInstanceRegistryImpl.java中。
public void evict(long additionalLeaseMs) { logger.debug("Running the evict task"); //主要是看isLeaseExpirationEnabled返回值 if (!isLeaseExpirationEnabled()) { logger.debug("DS: lease expiration is currently disabled."); return; } //进入筛选过期实例的方法。这里省略 }
public boolean isLeaseExpirationEnabled() { //isSelfPreservationModeEnabled由是否开启保护模式配置决定,默认为true if (!isSelfPreservationModeEnabled()) { return true; } return numberOfRenewsPerMinThreshold > 0 && getNumOfRenewsInLastMin() > numberOfRenewsPerMinThreshold; }
主要看numberOfRenewsPerMinThreshold和getNumOfRenewsInLastMin()方法。我们主要看numberOfRenewsPerMinThreshold初始化的地方。getNumOfRenewsInLastMin()方法是统计最后一分钟内的心跳统计总数。
//PeerAwareInstanceRegistryImpl.java public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) { // Renewals happen every 30 seconds and for a minute it should be a factor of 2. this.expectedNumberOfRenewsPerMin = count * 2; this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold()); //.... }
count是注册在注册中心的实例总数,包括高可用的另外注册中心。我们可以看到,这里是以硬编码的方式初始化expectedNumberOfRenewsPerMin,通过 实例数*2。为什么*2,因为实例默认发送心跳时间是30s,所以通过*2统计一分钟类应收到的总的心跳次数,因为是硬编码,所以不建议修改实例端心跳周期时间!。numberOfRenewsPerMinThreshold是通过总的心跳数乘以允许失败的比例。默认为0.85。expectedNumberOfRenewsPerMin在默认情况下,会每隔15分钟刷新一次。
通过上面分析,我们大致了解了不通过关闭自我保护模式下触发服务剔除操作的条件。得出以下两种方案来实现失效节点的剔除(亲测有效)。
Spring Cloud Eureka的自我保护模式与实例下线剔除
标签:new news interval 筛选 服务 就会 可靠性 expect eureka
原文地址:https://www.cnblogs.com/ibethfy/p/9593732.html