写点什么

注册中心 Nacos 异常实例需要 30s 才能剔除 Nacos 心跳时间设置(踩坑)

用户头像
laker
关注
发布于: 2021 年 02 月 07 日

前言

问题现象

  • 在 Nacos 控制台观察一个健康的实例

  • 模拟异常崩溃,把它强杀掉(kill -9)

  • 一直刷新观察控制台,大概要等到30s才会把实例剔除(大概 15s 设置不健康)

排查

其实很容易想到,这是默认心跳超时配置以及剔除策略配置导致的,然后各种 debug 源码以及官网 issue 搜索。

结论如下:

Nacos 1.1.0 以及之后的版本支持服务自定义心跳周期


之前的版本中,客户端注册服务时,不能自定义上报心跳的周期以及客户端下线时自动删除实例的间隔。在 1.1.0 中,我们支持了这个特性,应用可以在注册时,通过设置实例的 metadata,来指定心跳周期、健康检查过期时间及删除实例时间。具体举例如下:


String serviceName = randomDomainName();
Instance instance = new Instance();instance.setIp("1.1.1.1");instance.setPort(9999);Map<String, String> metadata = new HashMap<String, String>();// 设置心跳的周期,单位为秒,这里将心跳间隔设置为3秒:metadata.put(PreservedMetadataKeys.HEART_BEAT_INTERVAL, "3000");// 设置心跳超时时间,单位为秒,这里将心跳超时时间设为6秒,// 即服务端6秒收不到客户端心跳,会将该客户端注册的实例设为不健康:metadata.put(PreservedMetadataKeys.HEART_BEAT_TIMEOUT, "6000");// 设置实例删除的超时时间,单位为秒,这里将实例删除超时时间设为9秒,// 即服务端9秒收不到客户端心跳,会将该客户端注册的实例删除:metadata.put(PreservedMetadataKeys.IP_DELETE_TIMEOUT, "9000");instance.setMetadata(metadata);
naming.registerInstance(serviceName, instance);
复制代码

直接用上面的代码实测了是可以的

spring-cloud-starter-alibaba-nacos-discovery有相关配置如下

spring:  application:    name: nacos-producer  cloud:    nacos:      discovery:        server-addr: 10.7.11.13:8848        heart-beat-interval: 1 #心跳间隔。时间单位:秒。心跳间隔        heart-beat-timeout: 3 #心跳暂停。时间单位:秒。 即服务端6秒收不到客户端心跳,会将该客户端注册的实例设为不健康:        ip-delete-timeout: 3 #Ip删除超时。时间单位:秒。即服务端9秒收不到客户端心跳,会将该客户端注册的实例删除:
复制代码

**但是不生效**,后抓包看了下,压根没有把配置的心跳设置发送到 Nacos 服务端。


继续分析代码

相关类如下


  • NacosDiscoveryProperties

  • NacosServiceRegistry

  • NacosRegistration

  • NacosAutoServiceRegistration

  • NacosServiceRegistryAutoConfiguration


关键代码NacosServiceRegistry.getNacosInstanceFromRegistration

	private Instance getNacosInstanceFromRegistration(Registration registration) {		Instance instance = new Instance();		instance.setIp(registration.getHost());		instance.setPort(registration.getPort());		instance.setWeight(nacosDiscoveryProperties.getWeight());		instance.setClusterName(nacosDiscoveryProperties.getClusterName());		instance.setEnabled(nacosDiscoveryProperties.isInstanceEnabled());		instance.setMetadata(registration.getMetadata()); // 就是这个		instance.setEphemeral(nacosDiscoveryProperties.isEphemeral());		return instance;	}
复制代码

NacosServiceRegistryAutoConfiguration -1

NacosRegistration -2 首先实例化

NacosDiscoveryProperties - 3

2-3 顺序颠倒了。。。


解决方案:


  • 先用代码注册 meta 吧,后边在研究 。。。


解决方案

直接配置 Dicovery Metadata 数据

- preserved.heart.beat.interval: 1000 #心跳间隔。时间单位:秒。心跳间隔

- preserved.heart.beat.timeout: 3000 #心跳暂停。时间单位:秒。 即服务端 6 秒收不到客户端心跳,会将该客户端注册的实例设为不健康:

- preserved.ip.delete.timeout: 3000 #Ip 删除超时。时间单位:秒。即服务端 9 秒收不到客户端心跳,会将该客户端注册的实例删除:

配置文件示例


spring:  application:    name: nacos-producer  cloud:    nacos:      discovery:        server-addr: 10.7.11.13:8848        metadata:          preserved.heart.beat.interval: 1000 #心跳间隔。时间单位:秒。心跳间隔          preserved.heart.beat.timeout: 3000 #心跳暂停。时间单位:秒。 即服务端6秒收不到客户端心跳,会将该客户端注册的实例设为不健康:          preserved.ip.delete.timeout: 3000 #Ip删除超时。时间单位:秒。即服务端9秒收不到客户端心跳,会将该客户端注册的实例删除:
复制代码

Nacos 控制台

舒服了



🍎QQ 群【837324215】

🍎关注我的公众号【Java 大厂面试官】,一起学习呗🍎🍎🍎

🍎个人 vxlakernote



发布于: 2021 年 02 月 07 日阅读数: 23
用户头像

laker

关注

日积月累,百战成神 2020.12.16 加入

8年Java开发、一线老兵,喜欢分享工作中遇到的问题和解决方案,也会分享自己的学习笔记及感悟。 公众号【Java大厂面试官】的作者, CSDN:lakernote

评论

发布
暂无评论
注册中心 Nacos 异常实例需要30s才能剔除 Nacos心跳时间设置(踩坑)