2017经历的那些灵异bug

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

鬼打墙

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

断头鬼

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

替死鬼

前几天,有一次发布后,一直收到邮件告警某个 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 ,还有一个就是错误收集上报的 js ,问了一下这两个 js 的维护者,果然统计日志的js,在那次发布的时候改动了,为了使用Object.assign,加了一个 polyfill ,然后和 base js 里面的 polyfill 冲突了,由于统计日志的 js 先加载,所以报错是在 base js 里面。
这个问题比较难排查的地方是:

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

总结

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

坚持原创技术分享,您的支持将鼓励我继续创作!