2022-06-27 03:19:39
一行JS代码导致FT.com网站性能下降十倍的原因在于使用了同步的深克隆方法JSON.parse(JSON.stringify()),该方法在数据量大且并发请求多的情况下阻塞了事件循环。
首页轮询GraphQL API获取数据并存储在内存中,请求失败时应保留之前的数据。
日志显示API请求失败,但响应时间远低于设置的5秒超时,怀疑问题出在首页与应用程序的连接上。
尝试使用keepAlive连接和分散请求,但未解决问题。
Heroku显示的响应时间异常,第95百分位数约为2-3秒,最大值有时达到10-15秒。
本地运行应用程序副本进行负载测试,使用Apache Bench每秒发出10个请求,共1000个请求。
使用node-clinic和nsolid分析内存、CPU和应用程序代码,发现事件循环滞后超过100毫秒。
通过n-solid的CPU分析器,精确定位到阻塞事件循环的代码行:return JSON.parse(JSON.stringify(this._data));。
每个请求使用JSON.parse/stringify进行深克隆,该方法本身不坏,但它是同步的,执行时会阻塞事件循环。
在FT.com的案例中,该方法在每个页面渲染中多次调用,处理大量数据,并且有多个并发请求,导致应用程序性能显著下降。
在检索数据时应用深度冻结,然后在数据被改动的地方克隆特定位,减少同步克隆的数据量。
修复后重新运行负载测试,响应时间显著缩短,错误次数降为0。
修复后,首页的响应时间恢复正常,错误率立即下降。
未来计划包括对其他应用程序进行类似分析,优化性能,并提高事件循环的可见性。