架构师大咖
架构师大咖,打造有价值的架构师交流平台。分享架构师干货、教程、课程、资讯。架构师大咖,每日推送。
问题介绍
最近,我们收到了一份报告,说用户在使用内部软件时Chrome突然崩溃了。这导致我们正常的客户服务受到了各种干扰,他们在回复客户的电子邮件或与客户通话期间,突然就看不到工作所必需的客户账户信息了。
图:Chrome窗口崩溃
本来这并不属于我们的工作范围,通常浏览器兼容性之类的问题由其他团队负责,所以我对调试浏览器一窍不通。我应该从哪里着手呢?于是,我求助于一位经验更丰富的队友,我们的产品基础设施团队以及IT团队。
第一条线索
我们首先尝试找出受影响的用户有哪些共同点。
我们很快了解到:
-
并非所有员工都受到了影响。
-
面向客户的软件似乎没有受到影响。
-
其他内部软件页面似乎都很正常。
-
这个页面并不是每次都会崩溃。遇到此问题后,用户反复尝试重新加载该页面,有时会崩溃,而有时则不会。
-
并非所有的内部页面都会崩溃,但其中有多个页面崩溃,包括访问最多的页面。
-
在
Safari
或
Firefox
中未发生此问题。
猜测一:Chrome的版本问题
我们最初猜测可能是Chrome的版本问题。于是,我们让其中一个受影响的用户升级他们的Chrome版本,初步迹象看起来问题有希望得到解决。然而,我们很快了解到,尽管安装新的Chrome版本后,页面的崩溃频率降低了,但问题并没有得到根除。
此次尝试,我们获得了以下新线索:
猜测二:Chrome扩展问题
也许是Chrome扩展的问题?我们尝试让其中一个用户禁用了三个核心扩展,崩溃就停止了,于是我们以为问题得到了解决。然而,当我们尝试使用访客配置文件(没有扩展)重现修复操作时,仍然看到了崩溃。我们又回到了起点。
难以重现的bug
我们的基础设施团队向所
有工程人员发送了一条消息,询问是否有人能够重现这个问题。令人沮丧的是,尽管我们的许多客户服务代表都受到了影响,但除了两名土耳其的工程师外,所有工程团队都没有报告任何崩溃。经过几周的努力,我们逐渐了解到以下情况:
-
出于安全原因,我们未启用Chrome崩溃报告。
-
从几周前的代码库中检出代码并没有解决问题,这表明该问题不是由于最近的代码变更引起的。
-
加载页面的静态
HTML
版本并不会引发崩溃。
-
使用开源的
Chromium
代替
Chrome
不会引发崩溃,因此我们无法得知哪一段
Chrome
代码出现了问题。
-
引起
Chrome
崩溃的不仅仅是一个内部应用,还有好几个。
-
删除页面的特定内容并没有解决问题。
-
禁用内部字体并没有解决问题。
为了回避这个问题,我们的用户开始使用其他浏览器,因此这个问题的紧迫性也有所缓解。由于还有其他重要的工作,因此这个bug的调查进度缓慢。在无法重现Bug的情况下,我们没有太多的线索。然而,我们希望解决这个问题,因为用户在Chrome中设置了书签/设置/首选项。我们认为,我们不应该要求用户避免使用这款流行的浏览器,并且我们仍然会定期收到来自各种用户的询问,问我们这个Bug的调查是否有了进展。
好运降临
有一天,一名工程师突然报告说她也受到了影响。她唯一的改变是下载了Grammarly桌面应用程序。
等等,真的吗?我们必须试试看能否重现这个bug。
-
下载Grammarly桌面应用程序。问题立即重现了!
-
删除
Grammarly
。问题没有消失。重启电脑,问题又消失了。
-
重新安装
Grammarly
。
Chrome
又开始崩溃了。
我们与许多受影响的用户确认,他们也在计算机上安装了Grammarly。于是,我们有了突破口!
进展
由于调试能力得到了极大改善,所以我们进行了一些尝试:反复修改代码,然后重新加载页面,直到页面崩溃。
我们的主内部应用构建于ActiveAdmin之上,但新的一部分使用了React。用React构建的页面没有崩溃。这么说是我们的ActiveAdmin代码引发了崩溃?
早些时候,我们了解到删除页面上的特定内容无法解决问题,因此我们开始查看多个页面共同的代码,比如主导航栏和侧边栏。值得注意的是,我们的React页面使用了不同的导航栏。
我们的主导航栏代码涉及很多元编程,追踪这些线索常常会让人更加困惑。最终,我们弄清楚了如何注释掉导航栏的一部分,直到最后我们找到了一行代码,注释掉该行代码Chrome就不会再崩溃:
这个小节叫做“My History”,它不同于主导航的其余部分,所有用户看到的内容不一定相同,它是针对每个用户定制的,显示的是每个用户最近访问的几个页面。我们发现即使页面成功加载,将鼠标悬停在“My History”上也会导致Chrome立即崩溃。
接近真相
猜测三:Turbo
我们的目光停留在了turbo: true。这可能是导致问题的原因吗?Turbo是一个gem,是我们为了提高Rails应用程序的速度而添加进来的,但事实证明这并非问题所在:Turbo是在Bug报告之后才引入的,我们了解到引入Turbo的工程师在这之前的几个月就遇到过Chrome崩溃的问题,甚至在问题报告给我们之前几个月。
那么dropdown的定义在哪里呢?我们使用一款名为Arbre的框架从这种类型的方法中元编程HTML。为了浏览内部结构,我向中一位对Rails有深刻了解的工程师寻求帮助。最后获得的相关代码如下:
这段代码生成的HTML如下: