很久一段时间里面,一直收到客户说我们的系统登录一段时间后就莫名其妙的掉线了.
我们使用了websocket协议,前端的JavaScript每隔时间长为x的一个周期,便向服务器汇报在线认证情况.而服务器在第一次收到这个汇报后,每隔时间长为2x的一个周期检查一次用户是否在活跃.如果不活跃了,那就判定下线.然后来到的汇报就是不被认证的记录.
看起来很好理解的一个架构,但是上线后却偏偏在客户的某个用户的机子里频发掉线问题.
发现问题,基本上是怀疑网络问题.有可能因为网络中断,而发不出汇报,客户也有在用VPN,所以起初也是这样子怀疑是网络问题.登录的IP也有在变化. 于是就没有继续跟进,跟客户解释说是网络问题.
但是后来客户继续反应这个问题,还是那个用户.没办法,我们做了日志,前端和后端都有.然后更了过去.日志比较详细的记录一些掉线的情况. 因为一直怀疑是网络的问题.所以他们的反应,也就是解释了说什么时候被服务器PASS,什么时候掉线,什么时候再次登录.
再到后来,貌似反应的情况就多了起来. 于是在前端JavaScript中添加了断网状态检查,如果上报在线的请求发不出去,就首先访问一次服务器,然后访问一次第三方的站点.如果这两个都没通过那肯定是断网了吧.极端情况下不考虑.反正把结果都保存在LocalStorage中,cookies值,以及IP都有保存. 待到下次登录的时候,可以联网的情况下就发送这些数据给服务器.虽然这个办法有点被动,但是当时看起来也确实只能是这样子了.
等到客户的再次反应,我们就开始检查日志的情况.发现居然没有日志,任何断网情况的日志都没有,简直要大喊奇葩.在本地有测试过,也有和同事一起测试了.断网都会有状态检查的结果生成的.但是到了客户那边连生成都没有吗.很是奇怪.而且最后一次认证记录,到服务器判断下线,再到未认证记录,中间有很大的时间差,几分钟到一个小时. 为什么掉线一个小时后才发请求来说我是否在线…和同事讨论了有没有可能是因为session过期,而websocket请求还在继续什么的.这种半登录状态.但是同事就说不可能,因为websocket的反应是几乎没有什么时间差的.
我就觉得那段断网代码肯定没被运行. 但是又想不到什么情况下代码没被运行.哎,经验少就是这样子了.只能想到可能是客户的机子在睡眠了.睡眠情况下可能没运行代码,也没发送数据,嗯,很合理的解释.但是又想到平时玩chrome的时候,tab会自动白掉,貌似会假死.但是没有深入的去想.总觉得休眠多一点于是想方设法的让客户的技术去查看是否有睡眠,但是当时对方并没有去看,也没回复我们.貌似就这样子不了了之了.
带到掉线问题再次被反应,就觉得这样子被动下去肯定不行了,出了issue,然后向上级汇报.然后要来了那台机子的windows 日志,对就是windows的. 自己检查了一遍,发现没啥问题啊,也没什么休眠的,倒是一个某国外杀毒软件在不停的启动然后停止,然后继续启动停止…
没办法了.同事重写了之前我觉得可能引发内存泄漏的那段上报状态的代码.setTimeOut做的周期任务,方法反复调用太多,可能会引发内存泄漏.更新上去,整天这样子也是不行,但真没办法了,把情况汇报给了老板,老板让检查UA和IP问题,这样子貌似又重新回到了起点,但更深刻的问题是代码没被运行…问了大神同事,因为频发于个别帐号,同事让我把帐号单独拿出来测试,我在开了个虚拟机测试了,结果很正常,嗯,数据非常正确.然后星期天想起还可以测试一下,于是就开虚拟机来继续测试,就挂着一个下午和傍晚,数据也是很正常的…
然后今天1月29号,就没登录了.中午过后,客户再次反应这个情况.于是就找了日志数据来分析. 综合了一下日志,看了我们系统的两份日志,以及服务器的请求日志. 终于在同事修改的基础上发现了一点眉目, 有两个请求,那个未认证的请求中某个变量被清除了,按理说应该是和之前的认证请求的变量迭代才对.但是为什么被清除呢,只有刷新才会出现这样子的情况.但是这个认证请求只有在登录状态下才会被触发,用户一刷新就会回到登录界面了,为什么还有一次未认证的请求呢.很是奇怪.想着会不会是浏览器帮用户刷新了.看到服务器的日志,发现当时是登录后的初始化操作了, 已经下线了为什么是突然的登录后初始化请求呢,为什么会造成这种半死状态呢.想着想着一切记录指向了之前想的TAB会被挂起的结果.
于是重新开了虚拟机,分配了512的内存.然后在虚拟机里面开启了扫雷,纸牌,空心接龙,还有贴吧什么的…哈哈哈.
刚刚开始的时候还没啥,后来过了20分钟,我回头一看,我们的页面居然真的被挂掉了,打开一片空白,然后突然又重新加载…BUG被重现.当时是比范进中举还要高兴…哈哈哈
然后一搜索这个问题,发现是chrome的一个特性.
让我们来打开一下chrome,然后在地址下输入
chrome://discards/
嗯,就是这货了.里面有个Auto Discardable的勾.自动舍弃标签.
输入这个
chrome://flags/#automatic-tab-discarding
看到这个是它自己的解释
If enabled, tabs get automatially discarded from memory when the system memory is low. Discarded tabs are still visible on the tab strip and get reloaded when clicked on. Info about discarded tabs can be found at chrome://discards. – Mac, Windows
然后在虚拟机上对标签进行了关闭. 最后的日志数据和客户的用户数据相差无几.虽然不敢完全确定是否真的是这个问题.但是已经有99%的概率.
解决方案: 让客户把这个东西关了.