文章目录
前言
问题现象
- 在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大厂面试官】,一起学习呗🍎🍎🍎
🍎个人vx【lakernote】