0%

一个三年前的Bug导致上线失败

上周某核心服务上线过程中内存瞬间飙升,导致上线失败。经查是一个三年前的bug引发的。

故障现象

  1. 17:10:开始发布B组
  2. 17:20:开始出现内存,接口超时报警;开发和SA开始介入
  3. 17:25:认为是新版本有问题立刻回滚
  4. 回滚后持续半小时问题没有出现

初步分析

根据开发反馈,本次上线功能逻辑非常简单,只有20多行代码,而且测试过程中没发现任何问题;于是,大家开始review那段代码,review后得出一致多结论,该代码没问题。逻辑非常简单,只有一个地方调用了一个方法;这个方法已经存在了好你年了,而且被多个场景在调用;另外,这个方法逻辑复杂,团队内没有人了解。大家一致认为这个方法不会有问题,毕竟经历了「时间的考验」。

重现

在测试环境又做了一轮压力测试,一切正常。根据目前点情况看来这个bug跟数据有关;就是说,可能是某条数据触发了这个bug的临界条件.所以,我们决定在生产环境发布一台机器做测试; 这次发布后5分钟后出现了内存飙升现象,马上切掉该机器的流量而且dump Jvm内存 。

问题处理

拿到dump文件后立刻启动MAT分析;发现占用内存最多一个对象有3000多万个,分析该对象的调用盏都指向了同一行代码;「这段代码正是经历过时间考验的代码」。review这行代码相关部分马上发现有死循环的问题,只是满足这个条件的数据不容易出现。而这次的数据正好满足了这个条件。找到了原因,解决方法就很容易了;修改完代码review后没问题,测试,上线后一切正常;至此,该问题解决。这里可能有人会说死循环一般会首先导致CPU报警,怎么没看到我们提到CPU到问题;因为这台机器是16核CPU,所以一个核跑满并没有触发报警规则 。

后续措施

  1. 必须严格执行code review,从流程上去控制
  2. 需要监控各项指标到同比变化

反思

我们总是强调code review到重要性,但执行的时候总有这样那样的原因导致落实不彻底;我不了解当时的情况,但这次的问题我相信只要做过code review是一定可以发现的。另外,我始终相信代码质量最终要依赖开发人员来保证,测试只能保证功能性问题。特别是一些非功能性的边界条件,只能依赖开发保证。