推空保护

服务消费者(Consumer)通过注册中心订阅服务提供者(Provider)的实例列表。当注册中心进行变更或遇到突发情况, 或服务提供者与注册中心间的链接因网络、CPU等其他因素发生抖动时,可能会导致订阅异常,从而使服务消费者获取到空的服务提供者实例列表。您可以在Nacos客户端或MSE Nacos服务端开启推空保护功能,以提高整个系统的可用性。

前提条件

客户端开启推空保护

使用限制

Nacos Java Client 1.4.1及以上版本支持客户端推空保护功能。

说明

为避免使用有风险的版本,请参见版本推荐MSE Nacos SDK的应用和Nacos SDK限制使用版本为客户端、Spring Cloud和Dubbo选择合适的版本。

操作步骤

  • 若您使用的是Java版本的Nacos-Client。

    1. 引入nacos-client依赖:

      <!-- ${nacos-client.version} 需为1.4.1及以上版本 -->
      <dependency>
          <groupId>com.alibaba.nacos</groupId>
          <artifactId>nacos-client</artifactId>
          <version>${nacos-client.version}</version>
      </dependency>
    2. 在程序代码中按照下列方式配置:

      Properties properties = new Properties();
      properties.put(PropertyKeyConst.SERVER_ADDR, "${mseNacos实例域名}");
      properties.put(PropertyKeyConst.NAMING_PUSH_EMPTY_PROTECTION, "true");
      NamingService naming = NamingFactory.createNamingService(properties);
  • 若您使用的是Spring Cloud Alibaba框架,请在应用配置文件添加下列配置。

    spring.cloud.nacos.discovery.namingPushEmptyProtection=true
  • 若您使用的是Dubbo框架,请在Dubbo配置文件的注册中心链接URL中添加下列配置。

    dubbo.registry.address=nacos://${mseNacos实例域名}:8848?namingPushEmptyProtection=true

服务端开启推空保护

说明

由于目前仍有大量多语言的客户端以及使用旧版本的Java客户端,MSE在开源Nacos的基础上增强了服务端能力,为您提供服务端开启推空保护的能力。

使用限制

Nacos引擎版本需升级至2.1.0.0及以上。具体操作,请参见升级引擎版本

操作步骤

Nacos引擎的版本不同,开启推空保护的方式也有所不同。

  • 若您的MSE Nacos引擎版本为2.1.0.0或2.1.0.1,无需任何操作,对应版本会自动开启推空保护。

  • 若您的MSE Nacos引擎版本为2.1.0.2及以上,需要通过以下操作开启推空保护。

    1. 登录MSE注册配置中心管理控制台,并在顶部菜单栏选择地域。

    2. 在左侧导航栏,选择注册配置中心 > 实例列表

    3. 实例列表页面,单击目标实例名称。

    4. 在左侧导航栏,单击参数设置。在参数设置页面的实时生效参数区域,单击forcePushEmptyProtectionForAllService右侧操作列下方的编辑

    5. 参数编辑对话框,选中右侧的,然后单击确定

      说明

      为保证业务的最高可用性,建议所有情况下均开启推空保护,即forcePushEmptyProtectionForAllService均选择

结果验证

当有服务触发推空保护时,您可以在服务消费者(Consumer)所处节点上的${user.home}/logs/nacos/naming.log日志中看到Trigger push empty protection for Service字样。

正常情况下,该信息不会频繁出现,如果频繁出现,可根据以下情况进行排查和治理。

  • 订阅不存在的服务。

    如果应用订阅不存在的服务,需要排查该应用是否仍需要该依赖关系。如不需要,删除该无效依赖;如仍然需要,需重新发布上线该服务的提供者。

  • 应用订阅的服务提供者为空。

    • 查看该服务的提供者是否频繁掉线。

    • 查看该服务的提供者是否与MSE Nacos集群的网络连接不健康,导致Nacos认为此服务的提供者已经下线。

定位触发推空保护的服务

错误信息中包含触发推空保护的服务。您可以通过Service{namespace='XXX'、group='xx'、name='xxxxxxx'、ephemeral=true、revision=0}得知服务消费者已订阅哪个空服务。

已知容易触发推空保护的主要场景

场景

触发原因

解决方式

Dubbo 2的兼容多订阅场景下,旧格式服务名为空。

Dubbo 2.7旧版本(2.7.6之前的版本)所注册的服务名格式与Dubbo 2.7新版本的服务名格式不同。Dubbo 2.7新版本适用多订阅的场景,即同时订阅旧格式和新格式的服务名。当所有提供者均为新版本时,旧格式的服务在Nacos中必定不存在,导致订阅旧格式时触发推空保护。

升级引擎至2.1.0.1以上版本,或升级Dubbo至2.7.17以上。具体操作,请参见升级引擎版本

Dubbo 3的兼容多订阅场景下,接口级服务为空。

Dubbo 3支持应用级服务发现,所注册的服务名不再是接口名而是应用名。为了支持旧版本平滑升级,同时订阅应用级和接口级的服务名。当所有提供者均为Dubbo 3版本时,接口级服务必定不存在,因此订阅接口级服务时会触发推空保护。

设置Dubbo配置dubbo.application.service-discovery.migration=FORCE_APPLICATION。具体操作,请参见Dubbo官网

Spring Cloud首次启动NacosWatch功能且没有其他实例副本的场景下,服务为空。

Spring Cloud Alibaba在新版本中新增功能NacosWatch,用于监听自身服务状态,该功能会在启动应用时监听自身服务。当该功能首次启动且没有其他实例副本时,由于注册中心没有该服务,订阅会触发推空保护,应用启动完成后恢复。

首次启动且无其他副本时忽略错误,或设置spring.cloud.nacos.discovery.watch.enabled=false关闭Watch功能。具体操作,请参见Spring Cloud Alibaba

Spring Cloud Gateway完全下线某服务场景下,服务状态未同步。

Spring Cloud Gateway会在启动时查询注册中心中目前所有的服务列表,并订阅所有服务。例如,某个服务在Gateway启动后彻底下线(全部实例移除),是因为注册中心自动摘除了下线服务,但Spring Cloud Gateway不感知,仍然继续订阅,导致触发推空保护。

目前Spring Cloud Gateway不支持动态感知某个服务完全移除后取消订阅,建议您重启Spring Cloud Gateway。

强制进行推空保护的场景

MSE Nacos 2.1.0.2及以上版本,引擎对推空保护的逻辑进行了优化,仅在开启forcePushEmptyProtectionForAllService时保护所有空服务列表。但若在以下场景,即使forcePushEmptyProtectionForAllService开关为关闭状态,为保证可用性和稳定性,系统仍然会自动启动推空保护能力。

  • 引擎节点在进行升级、重启或故障自愈时,节点将所有服务自动开启2分钟的推空保护,以保证此期间用户业务可用性。

  • 当服务下所有实例全部移除时,集群将针对该服务自动开启1分钟的推空保护,防止因网络抖动、服务提供者短时间内发生故障等问题导致的异常推空,以保证此场景下用户业务可用性。

说明

为保证业务的最高可用性,建议打开forcePushEmptyProtectionForAllService开关,即在所有情况下均进行推空保护。