• 回顾nacos的一次严重事故,节点意外全部离线


    微服务进行容器化升级后,为了适应容器随时启停、自动扩缩容的情况,不影响系统的可用性,对服务的发布、更新进行了一定的改造。其中就有导致本次事故的原因。

    有一个服务在凌晨开始出现不可用状态,依赖该服务的系统大量出现"no available services",在没有任何人操作的情况下。这是一个非常危险的问题。

    从当时时刻的节点看浏览确实不再打入

    CPU资源明显下降

    内网流量明显下降

    经过初步排查,当时出现了一个容器回收,即自动启动一个新容器,停止一个要被回收的旧容器(AWS中有一种fargate节点,成本非常低,但不足之处是可能随时被回收)。

    由于这个操作触发了A服务的所有节点下线。

    正常情况,两个节点的服务有一个节点被停止,接着启动一个新的服务节点,不会影响没有变化的节点,但从nacos控制台上看到,确实两个节点全部出于离线状态,健康检测都是true,说明服务心跳都在常维持着。

    此时先紧急在nacos控制台操作上线,让两个服务节点处于在线状态,然后再细查原因。

    回到测试环境,我们模拟搭建了与线上同样的nacos集群(三个nacos节点,+一个LB对外提供服务),如果怎么操作,都无法复现线上场景。

    拉出出问题时,nacos节点的全部日志,进行仔细分析。

    1.新节点启动,成功连接nacos

     2.服务节点状态同步,具体触发原因不清楚

     日志中有一个dataSize=1,此时表明在线节点已经只剩下1个了,从后面的状态列表能观察到:

     此时三个节点注册上来,并且全部健康检测状态都是true。但是只有第三个节点的enabled属性是true,即在线状态。

    3.开始回收旧容器

     可以看到有一个节点与nacos断开了连接,紧接着就出现了全部服务离线情况:

    enable属性理论上只会通过设置变更,不是通过自动检测获取,此时想起该服务配置了默认下线状态,在服务启动代码中支持主动上线,以此来规避服务未启动完成就有流量打入导致出错。但上线时提前配置了默认下线,但启动代码主动上线未发布。所以可以解释新容器启动后处于离线状态。

    但依然无法解释有一个本来在线的服务节点,在容器新启动后变成了离线状态。

    继续分析可能导致节点变成离线的情况:

    1. nacos操作下线

    2. 发布系统调用nacos API下线

    3. 服务配置默认下线启动

    前两种情况,已经排除,只剩下第3种。

    第三种的影响有两种场景:

    1. 初始启动后服务一直处于下线状态

    2. 心跳中断,网络中断等,与nacos恢复服务时会如何?

    第2点这个大胆的猜测,在测试环境做一次复现,看看结果。

    (Nacos的临时服务节点维护机制:30s没上报心跳,服务会被自动移出)

    第一场景:服务启动配置默认下线,但启动时通过代码执行上线

    1. 服务正常启动 --> 先断开服务网络,时间超过30s+ -->服务从注册列表剔除 --> 恢复网络 --> 服务进入注册列表 状态正常:上线状态

    2. 服务正常启动 --> 断开服务网络状态30s内 --> 服务存在注册列表,但状态异常: 下线状态

    第二场景:服务启动配置默认上线

    1. 服务正常启动 --> 先断开服务网络 时间超过30s -->服务从注册列表剔除 --> 恢复网络 --> 服务进入注册列表 状态正常:上线状态

    2. 服务正常启动 --> 断开服务网络状态在30s内 --> 服务存在注册列表,状态正常: 上线状态

    所以出现网络问题中断,心跳恢复时会出现状态不正常的场景。目前已停用服务启动默认下线设置。

  • 相关阅读:
    Redis 与其他数据库的不同之处 | Navicat
    结合CRM 与项目管理,扩大你的业务和客户群
    云原生之nacos架构一览解读
    5、Docker安装mysql主从复制与redis集群
    JWT学习
    RTOS(6)任务管理
    Flutter 打包APK aab
    (带c++程序)个人对卡尔曼滤波在程序中的实现的理解
    JavaWeb — JSTL标签库
    Apache Doris 系列: 基础篇-Stream Load
  • 原文地址:https://blog.csdn.net/feng_zi0yhv/article/details/126782970