服务消费者(Consumer)通过注册中心订阅服务提供者(Provider)的实例列表。当注册中心进行变更或遇到突发情况, 或服务提供者与注册中心间的链接因网络、CPU等其他因素发生抖动时,可能会导致订阅异常,从而使服务消费者获取到空的服务提供者实例列表。您可以在Nacos客户端或MSE Nacos服务端开启推空保护功能,以提高整个系统的可用性。
前提条件
客户端开启推空保护
使用限制
Nacos Java Client 1.4.1及以上版本支持客户端推空保护功能。
为避免使用有风险的版本,请参见版本推荐和MSE Nacos SDK的应用和Nacos SDK限制使用版本为客户端、Spring Cloud和Dubbo选择合适的版本。
操作步骤
若您使用的是Java版本的Nacos-Client。
引入
nacos-client
依赖:<!-- ${nacos-client.version} 需为1.4.1及以上版本 --> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>${nacos-client.version}</version> </dependency>
在程序代码中按照下列方式配置:
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及以上,需要通过以下操作开启推空保护。
登录MSE注册配置中心管理控制台,并在顶部菜单栏选择地域。
在左侧导航栏,选择注册配置中心 > 实例列表。
在实例列表页面,单击目标实例名称。
在左侧导航栏,单击参数设置。在参数设置页面的实时生效参数区域,单击forcePushEmptyProtectionForAllService右侧操作列下方的编辑。
在参数编辑对话框,选中值右侧的是,然后单击确定。
说明为保证业务的最高可用性,建议所有情况下均开启推空保护,即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配置 |
Spring Cloud首次启动NacosWatch功能且没有其他实例副本的场景下,服务为空。 | Spring Cloud Alibaba在新版本中新增功能NacosWatch,用于监听自身服务状态,该功能会在启动应用时监听自身服务。当该功能首次启动且没有其他实例副本时,由于注册中心没有该服务,订阅会触发推空保护,应用启动完成后恢复。 | 首次启动且无其他副本时忽略错误,或设置 |
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开关,即在所有情况下均进行推空保护。
相关文档
通过MSE注册配置中心提供的高可用能力,可以有效提升应用应对风险的能力。更多信息,请参见MSE注册配置中心高可用最佳实践。