原因是项目中使用了nuxtjs框架开发,开发测试过程中没有出现异常。部署上线正式生产环境后,运行五六天后,节点异常,服务停止响应,pm2管理平台无法恢复应用。需要进入生产环境重启项目。查阅运行日志后发现,生产服务器会慢慢积累tcp连接数。达到一定程度后,会导致node程序占用cpu100%,停止响应。初期以为_nuxt下的文件不是通过nginx访问的,而是通过node读取的,导致打开的文件太多。重新配置nginx静态文件读取规则后,问题依旧。在解决这个问题的过程中,发现一篇文章提到,如果node内存泄漏,会导致node进程跑满当前cpu,打开文件数飙升。Debug调试工具node-heapdumpchrome调试工具调试过程安装node-heapdump。npminstallnode-heapdump--save-dev打开项目根目录下的nuxt.config.js文件进行heapdump配置。//内存快照代码varheadpdump=require('heapdump')//setInterval(function(){console.log('stheadpdump')headpdump.writeSnapshot(function(err,filename){console.log('dumpwrittento',filename)})},15000)module.exports={...//nuxtconfiguration}我设置heapdump每1.5秒拍摄一次内存快照。并在间隔期间执行以下操作。加载页面,等待快照,刷新页面,等待快照,等待快照完成,heapdump会将快照文件保存在项目根目录下。接下来,我们打开chrome开发者工具,切换到内存选项卡,点击加载,加载根目录下hepdump生成的文件。加载首页快照和刷新后的快照。我们点击切换右侧下拉箭头的视图选项卡类型。单击以将视图切换到比较。等待Chrome对比两个文件后,就可以看到第二个文件的内存快照信息了。查看右侧的#Delta选项。可以看到,一次刷新后,增加了69个闭包,没有释放。展开闭包(closure)可以看到大量request请求没有被释放。可以看出问题出在项目中的server请求服务接口上。要解决此问题,请检查服务文件中的请求方法代码。从'./url'导入Urls从'./fetch.js'导入Fetchletfn={}Object.keys(Urls).forEach(key=>{fn[key]=(data,headers)=>{returnnewPromise((resolve,reject)=>{resolve(Fetch(Urls[key].url,{method:Urls[key].method,data,headers}))})}})exportdefaultfn发现了一个问题,通过return请求Service,但是使用的数据通过箭头方式传递给下一层,层层引用变量,会导致闭包没有完全释放。因为传入的数据一直被引用,无法gc,这也导致node打开的tcp连接无法关闭释放。我们修改了services方法,修改后的代码如下:importUrlsfrom'./url'importFetchfrom'./fetch.js'letfn={}Object.keys(Urls).forEach(key=>{fn[key]=function(data,headers){returnFetch(Urls[key].url,{method:Urls[key].method,data,headers})}})exportdefaultfn调试生成内存快照再次处理,发现requestclosures都被回收了。内存泄漏问题已经初步告一段落,更新后项目稳定运行。参考文章来源http://frontenddev.org/link/j...文章首发于https://www.yodfz.com/detail/...
