一次node内存泄漏排查和解决
2024-05-18 11:40:27
背景
公司需要对接各种渠道,进行渠道管理进行了统一规范,生成了 ChannelManager 这个类,上线后发现一直报警,内存居高不下,而且走势呈阶梯上升,判断发生了内存泄漏
技术栈
Nuxt
基于 nuxt 和 vue 开发的一套前端代码
nodejs 性能平台
alinode,一个 ali 官方出的用来监控整个 node 内存和机器运行情况的程序,非常好用,问题是数据有一定延时
解决的步骤
首先尝试临时解决问题
因为线上一共有四台机器跑 ssr,所以通过设置不同的 crontab 进行分批重启 pm2,使得服务不间断
下线问题的 feture
最近上线的 feture 只有 channelManager,于是回滚代码之后重新发布,发现问题解决,找到问题代码区域
CodeReview
开会大家回顾整个问题代码,分析之后发现可能的问题在于使用了 global 的 mixin,改成 Vue plugin 的形式使用,具体可以参考这个 issue
测试环境下发现问题依旧没有解决
验尸
对比了最近几次 alinode 抓下的堆快照,发现所有的闭包都是 vue 实例,而且都会有一个同样的 key$channelManager
找出问题所在
最终发现是上 channelManager 的时候在 nuxt 的 plugin 中使用了 inject,因为 inject 的时候是同一个实例,本身的目的是可以获取 channel 列表
1 |
|
原因
在于 v8 的整个 gc 机制在于是否能够被访问到,因为 inject 之后不知道为何从 channelManager 能够访问到所有 inject 之后的 vue 实例,所以这一系列的 vue 对象都不可被回收