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

有一个服务在凌晨开始出现不可用状态,依赖该服务的系统大量出现”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内 –> 服务存在注册列表,状态正常: 上线状态

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