本周以不错的工作量完成两个活动的跨服的各种异常测试,设计模块不多,但是细节有点,涉及数据库,消息走向,优化,重构…一直忙到周五下班,在快下班的时间点,反馈过来几个线上问题。
奇怪的是之前版本没有出现,或者玩家没有反馈?本地没有测试出来。
上周改跨服时遇到的必现bug有,数据库每重启一次,某个对战数据库里第一名的数据多一份,比如有数据ABCD…经过几次重启最后可能是AAAA…BCD被顶替掉,这样的现象。
因为初始数据有两百条在DB中,开发人员不大会重复校对数据是否正确,况且需要每次shutdown业务进程才会多一个,顶替掉第二名,玩家参与该活动,拉取随机三名战力相近的对手信息挑战刷新排行榜,只有战力很高到前几名刷新时,才可能发错问题…还要重启多次…因为当时太忙交给另外同事去,据说很可能是跟更新有关。
后面几个线上反馈的问题比较很难复现。第二个是在安全区被击杀,因为在角色死亡时会有几种复活方式,要么花钱就地复活,要么不花钱等超时回原地复活,不同场景选择不同。因为之前在就地复活的时候没加保护免受攻击buff,导致花钱复活又被秒掉,所以后期加了个几秒的保护。把角色送回安全区,加上无敌buff免(受)攻击,并且在进入安全区和离开安全区都会有提示,这是正常的情况。线上反馈异常情况的视频是,角色死亡,提示被xxx击杀,界面弹复活倒计时,走完后回到安全区,此时并未有回到安全区的提示,并且未加无敌buff,角色还受到其他角色的攻击,但提示未命中,角色还在安全区内,大概十几秒种,该角色再次被击杀,再次超时复活后,提示进入安全区并加无敌buff,但击杀的角色在我的视野较远处(因为可能由于客户端设置只加载少些对应的模型数据,正常情况不太可能输入伤害那么远)。
经过分析,被击杀角色在服务器上的位置还在原处或附近,但客户端的位置在安全区,两边位置不同步,为什么这个分析是成立的?从视频中看,双方都在相互的视野中,且我瞄不准对方,因为距离太远,而对方可以瞄到我这个角色,可能我在对方视野中较近可以打到。经过本地几次测试无法复现,分析代码实现,其实很简单的逻辑,并没有在中间因为move和发同步包有改变角色状态的操作,导致move失败,且操作不可中断的。且底层的安全区逻辑一直没有出现过问题(当然不能说明没有问题),这种情况比较难查,当然肯定是个bug,就是不知道怎么引起的,另外日志中也不会记录这种日志。后来让负责此模块的相关同事帮忙看下也没发现什么问题。如果说一个函数代码块,判断a成立后继续走下去,再判断a也是成立的,而不会不成立,且函数无阻塞或挂起被打断操作,因为是单线程处理此角色数据的。后面这个问题再尝试分析下。
第三个是几个玩家登陆不上游戏,之前在游戏中,因为后台日志中记录此角色数据出错导致的。上周改过因为时序引起的问题,经分析和使用新旧代码测试,这个问题不是此修改而导致的。查看本服,大概是agentA被分配给userA,userA登出,然后agentA分配给userB(正常情况没问题 ),此时userA的某些数据还操作agentA(出问题的表现),是很奇怪的现象。继续查看本服日志,发现userA出问题前的几分钟去的跨服,查看跨服日志发现,userA参与某活动,跳到跨服副本(副本结束会有结算弹框提示一分钟,若玩家没点离开则一分钟后副本销毁自动把玩家送到上一个点),此时副本结算后的十几秒,此时进行登出处理,本服有登出处理和日志,并释放agentA,此时agentA分配给userB,跨服中并没有相关释放userA的日志,一分钟结束后把userA通过agentA跳到上一个场景,那么这里出现问题,跳不过去,因为agentA已被回收分配给userB,这就是问题所在。这样的情况导致的问题有多种,一是那边会定时把本应该销毁的user对象数据定时同步到agentA(若在跨服场景遇到这种情况),但是不会被同步的,并打印一些error日志;二是userA上线,并且被重复断线再重连,无法再进行游戏;三是可能影响到其他使用agentA的玩家...
本地复现多次和review代码是没有问题的,可能是由于什么操作导致异常?另外,副本结算界面期间,角色是不能点其他ui除了离开副本选项。所以在弹结算期间登出游戏,是怎么操作的也比较奇怪,日志中也没有因为收不到心跳包作几分钟后的下线处理的日志,这块是正常的。
周一回公司再次查看日志,第三个问题中,有条关键日志表示底层socket出现错误…后来review下这块基础代码,发现写的有问题。主要还是本服和跨服之前的连接管理,处理异常的情况没有考虑全面。导致跨服上那些资源没有销毁干净,而本服进行登出处理。于是修改几行代码,然后再次分析登陆流程,发现也有隐患并复现异常,后来根leader一起讨论合理的解决方案,最后修复测试都没问题。另外第一个问题也解决,本服服没有出现,跨服出现问题,因为保存DB的方式不对,所以导致数据错乱,有点郁闷。
这几个bugs不是那么难解决除了第二个,只是花很多时间去复现,可能会耽误其他重要的工作和节点,但是又不能不管,万一在后面影响面扩大就非常严重了。当然,根据之前定位偶现的bugs经验来看,这几个可能触发条件可能由多条件决定。对于游戏业务中,一个操作,比如登出过程,是不能被其他操作打断的,这里的打断是状态的改变,可能由于业务框架的不同,解决方案也是不一样的。好比早期tcp协议设计中,一条连接如果被复用,那么之前老连接中迷路的数据包被新连接当成数据,如何处理?这里的情况也是一样的。当然,代码反复测试也可能有潜在的bug,并不能测试完全没有问题,但是,当出现问题时,如何有何快速的根据有限的信息去定位,复现和解决,解决后怎么更新到线上去都是需要考虑的。