2017经历的那些灵异bug

930 阅读6分钟
原文链接: wulv.site

2017年快要过去了,回顾这一年来,在业务代码里,开发新功能占据70%,修复bug占了30%,在解决的这些bug中,大部分都是代码级别的错误,使用Chrome Devtools基本都可以解决,但其中有三个比较神奇,算得上是灵异事件了。

bug1

有一次后端同学重构了一下DSP广告平台的接口,让Java服务化提供接口,PHPweb控制层掌管路由和透传接口,于是对之前的接口URL重新规划统一了一下,内测没问题后就高高兴兴上线了,然而没过多久就有商家上报说页面报错没数据,于是我感觉复现,但怎么都复现不出来,然后问商家浏览器是不是版本太低,网络是不是不稳定之类的,但商家的浏览器和网络环境都没问题,这就纳闷了,于是果断找了一台Windows机器(因为我们都是Mac而且没装虚拟机),让商家加QQ远程协助看一下到底报了什么错,倒腾了半天,连上商家电脑,复现果然报错了NetWork Error,打开Chrome Devtools一查,ajax请求没发出去。。。我去,这是什么鬼,请求为毛发不出去了?看了一眼浏览器上那一排插件,怀疑是不是插件搞的鬼,一个个查看居然有屏蔽广告的插件,大哥,你特么自己都在我们平台上投广告,你还装屏蔽广告插件。。。果断让他关闭这个插件,然后果然没问题。原来我们的接口url里有advertisement这个单词,插件直接屏蔽了这个接口。没过多久,又有一个商家报页面没数据,呵呵,我们直接叫他关闭浏览器屏蔽广告插件,结果商家告诉我还是不行。。。😓,还是远程协助查一下,发现开了隐身窗口,接口还是没返回数据,看到商家电脑右下角运行的系统杀毒软件,眉头一皱,难道是这货搞的鬼?打开设置一看,果然有屏蔽广告这个选项。。。果然国产软件都流氓,你这所有的浏览记录都被人家知道了啊。第二天果断把advertisement改成gg(guanggao),整个世界都清净了。

bug2

过了一段时间,我司基于sentry搭了一个前端错误监控平台,可以收集客户端错误,上报到这个平台然后邮件告警开发者。收集的信息包括商家系统、浏览器版本、IP、操作路径等,这样就不需要再用Windows远程了。某一天,告警平台发邮件报错,店铺选择页面js运行报错,那还得了,选择不了店铺,相当于我们的后台入口挂了啊。果断按照报错的操作路径操作一次,又没复现。再一看操作系统与浏览器版本,找了一个一模一样的环境,还是复现不出来。晕了,还是用远程协助吧。商家那里确实有js运行报错,由于线上js也没有source map,压缩的代码也看不懂,查半天也没查出什么东西。返回sentry后台,反复比对各条报错。结果发现IP都是差不多的范围,一查果然都是合肥电信的运营商,难道所有合肥电信的cdn这个js有问题?然后果断报给运维同学,他把那个js下载下来一看,果然长度不一样,和正常的js比,少了一小段。肯定是cdn同步的时候,出了故障,果断把锅丢给七牛。

bug3

前几天,有一次发布后,一直收到邮件告警某个basejs运行报错,涉及的浏览器版本都是Chrome 31到37,果断轻车熟路开虚拟机复现,找半天找了一个Chrome 31,确实报错了,然而报错内容看不懂。想着那天发布内容包括升级基础react组件,加了一个babel runtime,还有一些其他的改动,难道是这些问题引起的?
然后尝试想让虚拟机Chrome运行本地代码,于是在win里面装nodegit、下载仓库、打包、把线上代码代理到本地。结果node-modules都装不上去,日了狗了。然后再试试装fiddler抓包软件,把打包后的代码放在win里面,抓取那几个js,替换成打包后的本地代码,然而还是看不懂,只知道是一个基础函数,可能是babel polyfill的问题,于是尝试把前端仓库那几天的改成一一revert,看看到底是哪个改动导致的问题。结果回退到发布之前都还是报错,这就尴尬了,至此我已经花了一天时间去排查这个问题,期间让几个同事一起排查也没发现问题本源。
最后想着把win的网络设置成Mac一样的网络,把win浏览器使用SwitchySharp设置成Mac的代理,这样就可以在win里面使用Mac的开发环境,(其实就是在Mac起一个node服务,监听一个端口,在这个服务里把所有的线上的前端资源(js,css)替换成本地代码,本地这个服务相当于一个网关服务器,还可以把网址指向不同环境的服务器。)结果惊奇的发现在预发环境是没有问题的,只有线上环境才有报错。我的第一反应是难道后端改造了什么数据类型?果断把线上数据和预发环境数据比对一下,然而一模一样。这个时候,对比两个环境只有两个差异了,一个线上环境多一个统计日志上报的js,还有一个就是sentry错误上报的js,问了一下这两个js的维护者,果然统计日志的js,在那次发布的时候改动了,为了使用Object.assign,,加了一个polyfill,然后和base js里面的polyfill冲突了,由于然统计日志的js先加载,所以报错是在base js里面。
这个问题比较难排查的地方是:

  1. 复现环境比较苛刻
  2. 后端仓库的改动(统计日志的js)和前端仓库产生了关联,版本回退难以排查
  3. 产生问题的js并不是出现报错的js

总结

出现bug在所难免,代码逻辑、浏览器兼容性、网络故障等等都会导致一些意想不到的问题,遇到问题首先不要慌,解决问题要有方法论,先把问题复现出来,然后使用Chrome Devtools,设置断点,观察数据条件,基本可以找出代码错误,其他问题,可以类似高中生物实验,结合条件对照,找出差异的条件,定位到问题,这个过程中需要敏锐的观察力。