记一次超级大坑-Vue对象在SSR服务端为单例状态
Madman 后端工程师

前言

这是一个让我一天两夜没安宁过的严重线上bug. 一开始测试跟我反馈说:”测试脚本有几率跑出H5页面无头部脚部左侧菜单栏组件的情况,并且页面无法点击部分图片资源无法加载。“我当时在忙其他的,随后去线上测试了一下,重现不了!我就继续忙其他的没在意。到了周六在家在家有空的时候想起测试反馈的这个问题。我想着重现不了,我就去分析一下转化数据吧,看看有没什么问题。一看数据吓我一跳,自测试跟我反馈问题的那天的时间节点起H5页面转化数据掉了近一半,整体平均浏览深度降了1/3。我立马召集小伙伴去公司加班排查,测试配合只能在线上环境测出问题,测试环境和alpha环境怎么都测不出来问题。重现不了的问题最难排查。耗费了我们前端团队一天的时间,最终终于在本地环境重现bug。

找问题步骤

  1. 对问题开始当天天上线的代码进行深度code review(并没到什么可疑代码)
  2. 想办法在测试环境重现(想要重现线上环境的问题,那就要找出测试环境和生产环境的区别)
  3. 尝试在测试环境跑高并发压测(然后也并没重现问题)
  4. 尝试在测试环境嵌入较多的H5页面,因为H5只有在App内才会隐藏头部脚部
  5. 检查SSR服务端渲染缓存策略。(能确认如果某个页面渲染的错误页面在服务端有短时间缓存,但是缓存策略也有做细分维度区分,站点级/地区级/页面级/AB测试级)
  6. 锁定我们用的Vue.prototype.$isFromApp(我们所有地方判断页面是否内嵌App都是通过这个状态判断)

大概率锁定是 Vue.prototype.$isFromApp 这个状态的问题

由于之前看官方的Vue.prototype.$isServer 就想着参考官方的思路维护一个判断是否是App内嵌的状态。所有页面根据这个状态判断页面App内嵌的特殊渲染逻辑。这个时候就埋下了这个坑(注意!!一定不要忘记Vue在服务端是单例状态,所有用户PV在服务端都是公用一个初始化好的Vue对象)。
我们内嵌App的链接跟App约定好的链接会带platform=app参数。H5会根据这个参数和其他一些js注入的信息计算维护Vue.prototype.$isFromApp这个状态。其实这个问题在很久前就是个问题,只是之前App内嵌H5的页面少,App并发请求进H5跟浏览器端请求抢更新Vue.prototype.$isFromApp状态的时机就少。而Vue官方Vue.prototype.$isServer不会有问题,因为每个用户请求在服务端的时候状态都是true。在客户端每个用户请求状态都是false。(所以不能再用$isServer的状态在mounted生命周期之前来判断做出不一样的内容渲染,不然也是会被浏览器接管失败并报错_frame.js:7 Uncaught (in promise) DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method. at Object.appendChild

实测确认Vue单例状态导致$isFromApp状态在多个请求间错乱问题

为了在测试环境和本地环境重现线上的bug情况,我们就需要造出测试环境和本地环境模拟内嵌App内高并发访问H5页面。我们清楚业务上是通过url里面的platform=app参数来判断App内嵌的。所以我就用 ab 压测命令

在终端用ab跑60000次请求,并发100。跑的链接带platform=app 让这些请求把Vue.prototype.$isFromApp高速的刷成true状态。

1
ab -n 60000 -c 100 -C "dynamicCdnCacheKey=wap:test" -H "User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1" https://hk-m.patpat.site/zh/article/sizechart\?category_name_app\=\&sizeUnit\=cm\&product_id\=441607\&platform\=app\&visit_from\=embedded\&timezone\=GMT%208\&version\=6.3.2\&user_token\=abdfgijmprtuzBCDEFHIMNQSVXYZ4569\&currency\=EUR\&position\=home-1823_hotarea_4-61054415430226c07204fafc_001

这个时候去浏览器放访问不带platform=app的链接,也会大概率按照Vue.prototype.$isFromApp=true的状态渲染无头脚页面。

在测试环境和本地环境重现了就好解决问题了,当确认这个问题的时候我内心”WOCAO“。

最后把这个Vue.prototype.$isServer状态删掉,把状态记录到了Vuex全局状态,因为我们Vuex是每次请求都创建的避免了Node端的单例状态问题

  • 本文标题:记一次超级大坑-Vue对象在SSR服务端为单例状态
  • 本文作者:Madman
  • 创建时间:2021-08-02 10:34:01
  • 本文链接:https://www.patpat.site/开发/前端/记一次超级大坑-Vue对象在SSR服务端为单例状态.html
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论