今天上午差点把东西搞坏,现在坐下来写这个,手还有点抖,不是怕,是后怕。
先交代下背景。我上个月刚接手一个很小的定时任务模块(就是把当天订单数据做一下聚合,出个报表),组里没人愿意碰的那种老代码,但也没人敢动它,因为它一挂整个业务报表就是一片空白。我接手之后一直小心翼翼,先补了接口用例,又在测试环境跑了半个月,才敢看核心逻辑。
今天早上我想改一个东西,也不算改逻辑,就是里面的一个配置参数,重试次数,那个值原来是3,我想改成5。原因是有时候上游数据源会抖一下,3次有点不够,这个是我自己观察的——上个星期有两次重试全失败了,要人工顶上去补跑,挺烦的。
好,就这行,我就改这一行。
改之前我惯例做了一遍检查:在我理解里,这个参数走的是重试分支,不会影响正常流程。而且我在测试环境里把重试次数改到5也跑过,没问题。然后我就改到生产,顺手看了一眼配置表,觉得配上了。确认了日志,任务还在待触发状态,我就去开会了。
然后到了快中午,我习惯性地看了一眼运行情况,结果发现任务挂了一排,全都是重试失败。
我当时第一反应是:什么情况?我赶紧打开日志,一条一条过(按我做测试的习惯,先复现再定位)。日志显示,任务组跑起来的第一批就挂了——不是业务异常,是数据库连接被拒。我再往下一看,连接池配置被改过?这不我改的行啊……
然后我想起来了。那个参数,我改的"重试次数",它在代码里不是只负责重试,它还间接控制了一个并发数。就那个,同一批任务里有个循环,循环的上限挂在同一个配置上。我理解它只是一个简单的重试次数,但实际上它还同时撑着另一块逻辑。就我这点水平,看一眼根本看不出来。
相当于我把3改成5,等于把并发从3提到5,上游那边连接数有限,直接被我自己打挂了。
这会我一直盯着屏幕,脑子里飞快地在想:该回滚就直接回滚,别侥幸,先保证生产再说。我按照预案把配置改回3,然后手动触发几个失败的任务去验证。还好,马上恢复正常了,后面几批数据没有丢,只是有一批晚出了四十分钟。组里有人问了一句"今天报表怎么出这么晚",我说上游数据晚了点,糊弄过去了。
但晚上看数据的时候,我发现其实还有一条任务跑完了但产出异常(它没有报错,是结果数字不对,这也是我习惯看数据的原因,同事可能根本不会发现),花了两个小时重新跑完。现在已经正常了。
当时恢复成功之后,我在座位上坐了一会儿,没跟别人说话,心里在想:如果我没有先改回去,而是想再调一调、试图救一下,可能现在全局报表已经挂了大半天了,这种事故就够我喝一壶的。
这个事给我的教训是——以后凡是我要改的东西,哪怕只改一个"看起来"无关紧要的参数,我都得先把它所有的引用点找全了再动。以前做测试的时候天天念叨边界边界,结果一到开发自己的代码,边界这个意识就自动关了。
不过话说回来,今天这个其实也验证了一件事:兜底做的越全,出事的时候越不慌。我真的好喜欢自己这个干了好多年测试才养成的习惯。想到再补吧,今天有点累了。