记一次前端慢请求的排查

109 阅读2分钟

背景

我们的业务场景,是消息中心。

前端通过长连接的方式与后端建立连接,接收消息。出于稳定性考虑,我们加了一个兜底机制,当长连接断开时,前端会通过轮询接口的方式继续请求新消息,我们将这个接口称之为 push接口。

突然有一天,线上报警,显示消息中心的 push接口慢请求率非常高,并且这些慢请求的耗时都是来自于前端。

排查

令人疑惑的是,我在监控里看到,这些慢请求的耗时都是来自于前端

这个 App Cache 的计算规则是通过 Resource Timing API - Web API 接口参考 | MDN 获取的 domainLookupStart - fetchStart。

也就是这个请求的耗时来自于 dns 查找开始之前的事件。通过进一步查看 Web API 定义,最终我了解到这个时间段大概率是浏览器请求缓存的时间。

而引起这个阻塞的原因在上图也可以看到,大概率是因为浏览器同时发起了过多的请求,请求阻塞了。

那么是什么原因导致了请求阻塞呢,开始我以为是轮询的逻辑有错误,会重复设置定时器,导致内存中的定时器数量过多,但是排查后发现并没有。

最终,通过对线上用户行为的分析,我发现,是电脑休眠时,定时器的堆积逻辑导致了请求数量爆炸。

在页面隐藏时,js 定时器会停止触发,但是定时器事件会一直堆积,当用户的电脑从长时间的休眠状态唤起时,堆积的定时器事件会迎来一次大爆发,结果也就是浏览器会一次发出所有休眠时间堆积的请求,造成慢请求。