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

966 阅读3分钟

文章目录

前言

问题现象

  • 在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

img