nacos版本: 1.4.5
运行环境:jre8/x86/3节点集群+nginx统一代理
现象描述: 将集群中某个节点关闭或启动时,偶尔会出现调用服务发现接口返回的hosts为空的情况。
排查过程: 在出现服务发现返回的hosts为空的时间点,nacos节点的naming-distro.log日志中出现以下记录,服务s4的数据被清理:
2023-04-10 10:14:25,949 INFO to remove keys: [com.alibaba.nacos.naming.iplist.ephemeral.project-1##env-1@@s4], to update keys: [], source: 10.0.0.2:8848
追踪定位: 日志出现在com.alibaba.nacos.naming.consistency.ephemeral.distro.DistroConsistencyServiceImpl#onReceiveChecksums中,该方法处理来自集群内其他节点的distro checkSum请求(/v1/ns/distro/checksum)。
查看该方法处理逻辑,发现在集群节点数量发生变更时,有可能会因各个节点更新healthyList速度不一致,导致处理checkSum请求时错误地移除了部分临时服务实例数据。
整理了一张个人猜测的状态流转图(“负责”指该nacos管理的服务(distro responsible),“缓存”指该nacos持有的服务实例数据,“节点”指该nacos持有的healthyList)。在下图【Step5】阶段,查询s4健康实例的服务发现请求发往Nacos3时,返回空数据列表。
问题分析
在DistroConsistencyServiceImpl#onReceiveChecksums处理中,会准备两个List:更新key(toUpdateKeys)、删除key(toRemoveKeys)。在上图的【Step5】阶段中,Nacos2和Nacos3的healthList不一致,两边都认为服务s4应该由自己负责管理,当Nacos3处理Nacos2发送的checkSums请求时,会将服务s4有关的key放入到toRemoveKeys中,同时并不会放入toUpdateKeys中,导致Nacos3上的服务s4实例缓存在一段时间内不存在:
建议
是否可以在DistroConsistencyServiceImpl#onReceiveChecksums方法的删除toRemoveKeys中key之前增加一段二次检查:“若该key的数据版本号与source server的版本号一致,将该key从toRemoveKeys中移除”?
原提问者GitHub用户BlackBAKA
nacos1挂掉, nacos2和3会重新计算责任节点,s1会被另外一个节点所负责,这个过程一般会小于心跳过期时间,除非你设置了过期时间为几个毫秒。
远离上 在客户端和服务端都是2.0以上的话, 使用长连接, 数据连接到那个节点,哪个节点就是责任节点,停止节点后长连接会飘到其他节点上,这个时间一般在1s内就会完成, 其他节点上旧数据会在3分钟之后才过期移除,期间这部分数据会重复一份。
原回答者GitHub用户KomachiSion
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
阿里云拥有国内全面的云原生产品技术以及大规模的云原生应用实践,通过全面容器化、核心技术互联网化、应用 Serverless 化三大范式,助力制造业企业高效上云,实现系统稳定、应用敏捷智能。拥抱云原生,让创新无处不在。