开发者社区 > 云原生 > 正文

1.4.5版本的集群节点数量发生变更时,distro checkSum时会删除节点中的临时服务实例缓

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时,返回空数据列表。

提问1.png

问题分析

在DistroConsistencyServiceImpl#onReceiveChecksums处理中,会准备两个List:更新key(toUpdateKeys)、删除key(toRemoveKeys)。在上图的【Step5】阶段中,Nacos2和Nacos3的healthList不一致,两边都认为服务s4应该由自己负责管理,当Nacos3处理Nacos2发送的checkSums请求时,会将服务s4有关的key放入到toRemoveKeys中,同时并不会放入toUpdateKeys中,导致Nacos3上的服务s4实例缓存在一段时间内不存在:

提问2.png

建议

是否可以在DistroConsistencyServiceImpl#onReceiveChecksums方法的删除toRemoveKeys中key之前增加一段二次检查:“若该key的数据版本号与source server的版本号一致,将该key从toRemoveKeys中移除”?

原提问者GitHub用户BlackBAKA

展开
收起
学习娃 2023-05-22 15:16:19 125 0
1 条回答
写回答
取消 提交回答
  • nacos1挂掉, nacos2和3会重新计算责任节点,s1会被另外一个节点所负责,这个过程一般会小于心跳过期时间,除非你设置了过期时间为几个毫秒。

    远离上 在客户端和服务端都是2.0以上的话, 使用长连接, 数据连接到那个节点,哪个节点就是责任节点,停止节点后长连接会飘到其他节点上,这个时间一般在1s内就会完成, 其他节点上旧数据会在3分钟之后才过期移除,期间这部分数据会重复一份。

    原回答者GitHub用户KomachiSion

    2023-05-22 20:14:17
    赞同 展开评论 打赏

阿里云拥有国内全面的云原生产品技术以及大规模的云原生应用实践,通过全面容器化、核心技术互联网化、应用 Serverless 化三大范式,助力制造业企业高效上云,实现系统稳定、应用敏捷智能。拥抱云原生,让创新无处不在。

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载