【apollo】使用不规范,开发测试2行泪

【章节】

开心上线 

痛失午休 

  • 问题浮现 
  • 尝试解决 
  • 深入分析 
  • 回溯过去 
  • 问题修复 

痛定思痛


开心上线

前段时间做了个新需求,在管理后台新增了一些运营配置项供运营使用,控制C端的一些开关类的东西。虽然涉及到的地方挺多,但也不难,测完开心上线,上线后立马验证,没发现什么异常,临近午饭点就准备吃午饭了。

痛失午休

问题浮现

午饭没吃几口,线上异常告警来,瞬间不香了,赶紧回来捞日志,根据日志的场景,我们自己在线上环境也复现了问题。然后就和开发大佬一起跟踪日志排查,发现主要错误是空指针,出错位置在at com.xxxx.xxxx.test.utils.CommonConfigUtil.getOriginAppIdsConf(CommonConfigUtil.java:842)确实是此次需求新增的代码,代码如下:

图片

可以看到这行代码是调用getAgencyByAppId方法,getAgencyByAppId方法里面实现如下,其中agencyItemConfMap是直接读取的apollo对象

图片
图片

虽然定位到了代码,但是我们百思不得其解,这明明是从apollo简简单单的读取一个配置而已,这个配置已经发布线上了,怎么就会报空指针呢?

而且,我们发布之后,我们也走过这种场景,当时也没有发现报错,怎么吃个饭的时间就出问题了呢?

尝试解决

我们先在沙箱环境使用线上相同的配置,来进行debug,结果并未复现问题。再看报错的代码,是读取apollo配置。所以我们怀疑:

难道是apollo发布了没生效,导致agencyItemConfMap是空的?

所以,我们手动把配置重新发布一次,再观察看是否能解决。

结果就是,线上告警还是在不断的出现。

此时,我们怀疑起了服务问题,难道是服务部署后没有读到这个配置?

所以,我们又手动把服务器重启了一次,再观察是否能解决。

结果就是,刚重启完还真的解决了,我们多次触发出问题的场景,均没有报错,心里舒了一口气。

然而,生活总不是这么顺利,过不了30s,错误又出现了,此时的心里是彻底崩溃的。

不过好消息是,虽然又出现了报错,但是概率低了一些,然后又在报错的日志中,寻找出错的服务器是哪一个,或许只是某一台机器的问题?

遗憾的时候,每一台机器都有对应的错误日志,一时之间都不知道如何是好。

深入分析

既然不是服务器问题,不是apollo问题,那肯定还是代码问题了,于是我们静下心来review代码,看到底是哪个地方出问题。

我们已经确定了apollo发布没有问题,而且重启服务之后的小段时间没有问题,难道是在某种场景下apollo的配置被谁改变了?于是,在小小的idea里面挖呀挖呀挖,我们想要挖出这个隐藏的大bug。

就这样终于在本次提交的代码里找到了如下代码:

图片

为什么要在这里remove呢,是因为需要去除那些过期、无效的appId,方便后续使用,但不曾想出现大问题。

getAgencyItemConfList方法如下:

图片

上述代码相当于,读取到apollo对象后,直接返回该对象,然后在该对象的基础上进行remove操作,这样做就导致了后续用户读取的apollo对象数据缺失,导致报空指针异常。

看,小小的bug就是这么朴实无华,让你欲哭无泪。

具体如下,两种对象操作方式

有问题的方式:所有功能操作的都是同一个apollo对象,那么一旦对象数据被某个功能修改后,后续所有读取到的数据都不是我们想要的

图片

正确的方式:所有功能查询的都是原始apollo对象,如果功能需要修改apollo的数据,那么应该返回一个新的对象,后续的增删改操作都是在新对象上进行

图片

回溯过去

通过git查看历史代码,发现之前读取allAppConfig的方法就是把apollo对象遍历出来放进新对象,再返回的,所以之前不会出现问题

图片
图片

问题修复

既然发现问题,这就好办了,只需要将读取到的apollo对象赋值给一个新的对象,然后返回那个新的对象即可。这样后续再进行操作的时候永远都是操作新对象,不会影响原始apollo数据,修复后的代码如下:

图片

修复上线后,观察一段时间,没有再报错了,绷着的心终于可以放下

痛定思痛

解决完问题,思考下,为什么测试&沙箱环境没有遇到呢?我认为主要是以下原因:

1、remove这个场景只在某种特殊条件下才会触发,本次未改动,测试时未回归此场景

2、测试&沙箱环境同时只有我一个用户在操作,无法在触发remove后同时又去查询

如何避免这种问题呢?我认为可以从以下方面去规避:

1、开发角度,规范apollo读取方式,如果是对配置数据有修改需求的,一定要以新的对象return出来,例如上述的惨案;

2、测试角度,有code review能力的,可以把本次提交都尽可能的过一遍,尽早发现问题;code review能力欠缺的,尽量多覆盖异常场景,捉住系统中的漏网之鱼;

3、能否在静态扫描阶段,通过增加sonar自定义扫描规则来识别出这种存在风险的地方,提前处理,这种方案还有待调研;

关于作者

程杰,深圳业务-金融测试组,主负责金融相关业务测试,金融mock平台建设

声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/308432.html

联系我们
联系我们
分享本页
返回顶部