框架升级带来的灾难

下午终于解决了困扰了我好几天的一个bug,这个bug的排查之旅十分艰辛,最后的解决方式出乎意料的简单.简单分析一下.

前提

这是一个新项目,从老项目移植而来,框架上从 spring boot 1.x升级到了2.x ,相关的依赖也都升级了.大家一起解决了升级过程中遇到的一堆坑,然后对老项目中的各个痛点进行改进..之后就是按部就班的移植业务逻辑,提测,事情进展到这一步是相当顺利的,前提是,没有这个bug!

测试提了几个bug,类似于 消息推送了两次,弹框出现两次,系统消息重复,主流程错误 等.

排查之旅

事情要分个轻重缓急,弹框出现两次,和系统消息重复这种问题不影响大局,而且看起来很像是前端的问题,因此这些bug先放到一边,先看主流程错误

没有什么是加log不能解决的,如果有,那就多加点

由于是移植的代码,逻辑我也不是特别清楚,上万行代码要是等全部理清了再处理黄花菜都凉了,首先想把这块逻辑和老代码比对一下,看下是不是移植的时候疏忽了,完全没问题! 怎么办? 加log,对和这块逻辑相关的代码的每一个关键步骤添加log,记录关键变量的变化,记录的时候一定要有一个统一的字段将他们关联起来,这样查看日志的时候可以观察到完整的流程,例如

...
logger.info("userId [{}] xxxxxxxxxxxxx",userId);
...
logger.info("userId [{}] xxxxxxxxxxxxx",userId);
...
logger.info("userId [{}] xxxxxxxxxxxxx",userId);

初现端倪

通过观察日志,比对代码中的关键步骤,发现是一个状态被错误的更新了两次,正常情况下它应该只被更新一次的,检查对应的dao层代码,看下是不是又copy的时候搞混了,检查下来没问题,再看更新状态对应的这个dao层方法的调用情况,和老项目做下对比,也没问题.

既然这里查不到问题,那么就查下出现问题这段时候的所有日志,经过艰难的过滤和查找,终于找到了一个关键信息: 这个逻辑的入口方法被调用了两次,因此状态才会被更新两次.

假象

进行到这里,我以为已经找到了问题的关键,这个时候我对这个bug出现原因的假设是: 有些逻辑会调用这个入口方法,那么应该是移植的时候这些逻辑copy错了,导致这个入口方法被调用了两次.那么下面的重点就是找出哪些地方调用了这个入口方法.

经过检查,这个方法分为内部调用和外部调用,外部调用会制定一个定时任务(定时任务这个模块有两个实例运行),间接传递给顶层模块,顶层模块会在计时到达时调用这个入口方法,内部调用则是其他逻辑中直接调用. 查看日志,根据其中一次调用对应的UUID,成功找到顶层模块中对应的调用日志.那么另外一个肯定是内部调用了,然后查找内部调用的逻辑,有牵扯出一大堆关联逻辑,一层调一层, 没办法,再次祭出log大法.一大堆log看的头皮发麻,这样边查边加log,苦苦挣扎了大半天,一无所获,此时心态爆炸,已经想要放弃,求教大佬了,然而根据现在查出来的数据,无法提供有意义的参考,自己的锅还是自己背吧,继续查.

转机出现

第二天早上,抱着死马当成活马医的想法,再次查看日志,发现两次都是外部调用,纳尼! 顺着这个思路,去查找制定定时任务的地方,看下是不是这里的逻辑有问题,经过艰难的log&查找,看到定时任务只制定了一次.再次陷入僵局.时间又过去了半天...离验收时间又近了,头疼.

换一个视角

再次查看日志,发现两次入口方法的调用时间十分接近.难道是顶层模块除了问题.首先解释一下定时任务制定的逻辑: 底层模块制定定时任务就是redis中存入一个key,顶层模块会轮询同一个redis,然后解析key进行调用. 这整个模块也是直接copy过来,基本没有改动,这次是真的无计可施了.只能求教大佬

柳暗花明又一村

将我调查出的所有线索告知大佬,大佬查找之后发现有很多定时任务都是很相近的时间被重复调用,大佬给出了指导,看下顶层轮询那里,加点日志看一下.这一查,果真查出了问题. 由于有多个(请注意,两个!!!)顶层模块实例存在,因此使用redis事务保证定时任务只被执行一次.之前的代码是这样判断事务是否执行成功的

List result=redisOperations.exec();
if(result!=null){
// 事务执行成功操作
}else{
//事务执行失败操作
}

问题就出在这里,由于spring boot升级了2.x,对应的spring data redis也升级了.而升级之后,当事务执行失败后,exec()返回的不再是null,而是空List.修改为以下代码后顺利解决

List result=redisOperations.exec();
if(!CollectionUtils.isEmpty(result)){
// 事务执行成功操作
}else{
//事务执行失败操作
}

反思

exec的变化之前是看到过相关文章的,由于其他地方代码也用到过这个事务,而且那些部分也经过了测试,所以从来没有向这块联想.没想过会是这里出问题

有哪些征兆没能意识到?

系统消息重复,两次弹框,消息推送了两次,从这些是能看出一些征兆的,结合顶层模块有两个实例,这些特征都被无意识的忽略了.导致在无意义的方向浪费了很多精力.

思维差异

时候问大佬为什么他第一印象是顶层模块有问题? 大佬说:

业务逻辑是移植过去的,如果有问题,早就乱套了

而我的第一印象是业务逻辑移植的时候出了问题,细想一下,这个印象站不住脚,移植业务逻辑,顶多出现遗落了一个分支代码或者错误删除一些代码.不可能出现张冠李戴这种问题.

总结

最终是大佬找到了bug的关键,是不是就意味着我做了几天的无用功? 不不不,在我看来,之前收集到的那些线索,很有用处,首先排除了很多不可能的判断.然后以我的视角给出问题的表现,再将收集到的证据展示出来,才能最终这么快速的解决问题. (如果在没有搜集到足够的证据之前就甩锅给别人,是不道德的,只会将一个人的痛苦变为两个人的痛苦)

代码不规范,同事两行泪, 在这个bug上的体现就是: 集合判空一定要用工具类,不要只是 list==null

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 2017.02.22 可以练习,每当这个时候,脑袋就犯困,我这脑袋真是神奇呀,一说让你做事情,你就犯困,你可不要太...
    Carden阅读 1,325评论 0 1
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,084评论 1 32
  • 一、温故而知新 1. 内存不够怎么办 内存简单分配策略的问题地址空间不隔离内存使用效率低程序运行的地址不确定 关于...
    SeanCST阅读 7,774评论 0 27
  • 谁也预料不到明天会是什么样子,我只能给明天一个期许,愿明年的这个时候,能出去走走,看看这个多姿多彩的世界。 十年,...
    喵个CC阅读 233评论 0 1
  • 知一书斋阅读 144评论 0 2