古老的偶现bug终于被...

2019-11-08  本文已影响0人  fooboo

这周遇到的问题值的总结记录下,这次记录三个问题。线上问题最近有些多哈,且之前出现的次数很少。

其一是线上项目再次出现内存泄漏,虽然没有oom杀掉进程,但是进程吃掉很多很多内存,然后这次情况和之前的两次还不一样,这次的机器配置更好,工作线程更多,代码虽然一样,但就是在这种情况下出现问题,十几个小时内存泄漏二三十GB,具体怎么分析的以及什么问题就不多说,最后也修复在线上跑两三天再也没有出现。重点说说第二个问题。

因为之前记录在excel表中遗留的几个偶现且没有解决的bugs,一直惦记着,想着什么时候再出现并彻底解决它们。就是偶现个别玩家技能数据等级被重置为一,因为登陆的时候并没有出现,而是在游戏中因为触发的某些操作导致的,然后重新登陆没有再出现。

拉取玩家数据再本地多次测试并没有出现那样的情况,数据本身是正确完整的。所以,这个问题是偶现bug,在某些边界情况下,而且玩家那边反馈来的问题,并没有具体描述什么情况下出现的,比如断线什么的。review服务器相关的技能逻辑,同步下去的数据,以及客户端那边的相关代码,并没有明显的发现,后来就没有再跟踪下去。

直到这次...

这次客户端那边收集到的某个模块数据的报错,对某个期望是table的类型索引某个key时,出现异常,结果是对number类型的索引某个key。查看相关的声明结构和该模块的逻辑时,并不会出现这种情况。然后阅读相关的底层代码和上层业务代码时,也没有明显的发现。

后来看报错的堆栈信息,发现是因为断线重连时,再次同步某些数据,赋值时出现的,所以根据这类信息,跟踪到调用关系后,发现底层代码在某个判断关系下,是一个个key-value设置的,而上层期望是table而不是这样的结构,所以出现问题。

简单来说,定义的数据结构类似:

local killmonsterdata = {
  count = 100,
  updatetime = 1222222,
}

服务端那边当初可能并没有考虑到效率,直接同步这样的结构,这儿先不说优化的事情。然后客户端逻辑直接监听该table变化:

local listener = addlistener(target, "data_set", "killmonsterdata", 
                 function() update(xxx) 
            end)

这里dispatch事件时,from->to正常情况下是table,所以这里直接from.count和to.count是没问题的,但在断线的时候,因为走的set方式不对,导致from/to是count的具体数值,会根据key个数抛多次事件,这里是两次。导致一些报错,并无法更新到上层相关的业务数据,造成两边数据不一致。

后来准备复现,因为要同时踩到三个条件才能触发这种报错:一是在断线重连的时候,二是在上面有报错逻辑的地方跑到相关业务代码,三是在更新值时不相等的时候。
至于第三个条件,是因为底层做了优化,即更新某个值时,如果本地的旧值和同步下来的新值相同则不更新,即不dispatch,所以这里会直接返回,而触发不到有问题的代码。

这里在服务器代码上,直接每次加一即可,然后手动把心跳包的处理直接返回,这样不更新心跳时间,则过一段时间后,会作断线处理,那么就会发生断线,然后需要去到特殊的场景,才能初始化相关的数据,并设置监听killmonsterdata更新事件,这样三个条件都准备好,开始复现。

当然,结果是如预期那样,断线时,会报错,而正常情况下,是没问题的,所以这个问题偶现在要同时满足三个条件,不然有些代码跑不到,即不会触发隐藏的bug。这个问题涉及到上面的技能数据被重置的情况,基本也是在这个条件下出现的。然后在修复这块问题代码时,也发现了隐藏的其他一个问题,可能当时也没测试到吧。

总结一下就是,有些代码路径确实很难都测试到,且可能因为底层的代码问题,导致上层的数据不对或者其他原因而不能及时解决。可能是偶现的,需要同时满足几个条件时比较难办。而且,如果错误传播出去还好,上层的错误更容易发现,这样两个问题彻底解决。有些问题还是要解决的,否则会影响正确性,体验相关,也可能导致玩家流失。

另外一个问题是有些玩家在进行某些活动副本时,导致卡顿转圈,而有些玩家不是这样,但反馈来的大都是在副本中,然后根据日志grep到确实断线重连多次,影响体验。后来查看相关的业务代码和底层网络框架,查找为什么会出现那样在的问题。因为代码还是同一份,为什么在有些平台是好好的,或可能极少数断线情况,而在另外的平台上,会出现大面积的断线重连情况。后来在本地通过几种途径测试,该副本的人数有二三十人同时战斗,并没有出现类似的问题。后来只好再跟那边的人反馈下,再收集些具体的信息帮助排查,是什么问题,基本不太可能是代码的问题。当然,大概是知道什么原因,解决的话,可能目前并没有更好的办法。

通过线上问题的分析和解决,复盘之前的相关业务代码,以及考虑问题的方式,确实能成长收获一些。

上一篇下一篇

猜你喜欢

热点阅读