NUXT内存泄漏引发问题

algodreamer
• 阅读 7534

起因

项目中使用了nuxtjs框架进行开发,在开发测试过程中均无出现任何异常。部署上线到正式生产环境之后,运行了五六天之后node异常,服务停止响应,pm2管理平台无法恢复应用程序。需要进入生产环境进行重启项目。查阅运行日志之后发现生产服务器会缓慢堆积tcp链接。在到一定的程度之后,会引发node程序 cpu 100%占用,停止响应。最初阶段以为是_nuxt下的文件并未通过nginx访问,而是通过node进行读取的,造成文件打开过多,重新配置了nginx静态文件读取规则之后,问题依旧。在解决这个问题的过程中发现某个文章中提到,如果node内存泄漏会造成node进程跑满当前cpu,并且打开文件数飙增。

调试

调试工具

  1. node-heapdump
  2. chrome调试工具

调试流程

安装node-heapdump。

npm install node-heapdump --save-dev

打开项目根目录的nuxt.config.js文件,进行heapdump配置。

// 内存快照代码
 var headpdump = require('heapdump')
//
 setInterval(function () {
   console.log('st headpdump')
   headpdump.writeSnapshot(function(err, filename) {
     console.log('dump written to', filename)
   })
 }, 15000)

module.exports = {...// nuxt配置}

我设定了每1.5秒,heapdump进行内存快照一次。
并且在间隔过程中进行以下操作。

  1. 载入页面,等候一次快照
  2. 刷新一次页面,等候一次快照

等待快照完成之后,heapdump会将快照文件保存在项目根目录中。

接着,我们打开chrome开发者工具,切换到memory选项卡,点击load载入hepdump生成在根目录的文件。
NUXT内存泄漏引发问题

分别载入第一次页面快照,跟刷新一次之后的快照。我们点击切换右侧下拉箭头的视图选项卡类型。点击切换视图到Comparison。

NUXT内存泄漏引发问题
在等候Chrome比对两个文件之后,可以看到第二个文件的内存快照信息。查看右侧# Delta选项。
NUXT内存泄漏引发问题
可以看到 刷新一次之后,增加了69个闭包未释放。
展开闭包(closure)可以看到大量的request请求未释放。
由此可见,问题出现在项目中服务端请求服务接口上。

解决问题

检查services文件中的请求方法代码。

import Urls from './url'
import Fetch from './fetch.js'

let fn = {}
Object.keys(Urls).forEach(key => {
  fn[key] =  (data, headers) => {
    return new Promise((resolve, reject) => {
      resolve(Fetch(Urls[key].url, {method: Urls[key].method, data, headers}))
    })
  }
})

export default fn

发现了问题,services 通过return请求,但是使用的数据都是通过箭头方法传递到下一层,变量被层层引用,这样会造成闭包无法完全释放。因为传入的数据一直都有引用无法gc,这样也造成了node打开的tcp链接无法关闭释放。

我们修改了services方法,经过修改的代码如下:

import Urls from './url'
import Fetch from './fetch.js'

let fn = {}
Object.keys(Urls).forEach(key => {
  fn[key] = function (data, headers) {
    return Fetch(Urls[key].url, {method: Urls[key].method, data, headers})
  }
})

export default fn

再次通过调试流程生成内存快照,发现request闭包都回收完毕。内存泄漏问题初步告一段落,项目更新之后已稳定运行。

参考文章来源
http://frontenddev.org/link/j...

文章初次发布于https://www.yodfz.com/detail/...

点赞
收藏
评论区
推荐文章
菜鸟阿都 菜鸟阿都
4年前
springboot+vue项目linux环境部署
项目部署是一个程序员必备的技能,当项目开发过程中,需要将项目部署在开发服务器上,进行自测,或协助运维,测试进行环境的搭建配置,学会了项目部署,你就是团队中最亮的那个仔。项目简介后端:springboot项目【打包为jar包】前端:vue项目【通过cli3搭建】目标服务器:liunx操作系统使用工具xshell:通过命令操作服务器sftp:上传安装包到服务器部
Stella981 Stella981
3年前
Feign请求响应结果被截取com.fasterxml.jackson.core.io.JsonEOFException
在生产环境使用feign调用外部接口时,偶尔会出现下面错误2020101511:00:18,535ERRORcom.shein.abc.rmp.controller.RecExplainConfigControllerrec_explain_query.failffeign.codec.DecodeExc
Wesley13 Wesley13
3年前
2019 年 CNCF 中国云原生调查报告
!头图.jpg(https://ucc.alicdn.com/pic/developerecology/6db0c465111b4d9a96eb1ffe85c00e7a.jpg)中国72%的受访者生产中使用Kubernetes在CNCF,为更好地了解开源和云原生技术的使用,我们定期调查社区。这是第三次中国云原生调查,以中文进行
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Solr搜索引擎 — SolrCloud安装和集群配置
!(http://pic.wblog.cn/F21D67BC6A7C498FACFF9F0E28C60A8A.png)搞定了一切的一切之后下一步就是正式使用了,但是之前介绍的都是在单台服务器上进行的部署,如果在生产环境出现了单台故障怎么办呢?提供稳定性和性能的最直观的方式就是集群,solr官方提供了cloud的集群方式附上:喵了个咪
Stella981 Stella981
3年前
Solr搜索引擎 — SolrCloud介绍和环境准备
!(http://pic.wblog.cn/F21D67BC6A7C498FACFF9F0E28C60A8A.png)搞定了一切的一切之后下一步就是正式使用了,但是之前介绍的都是在单台服务器上进行的部署,如果在生产环境出现了单台故障怎么办呢?提供稳定性和性能的最直观的方式就是集群,solr官方提供了cloud的集群方式附上:喵了个咪
Stella981 Stella981
3年前
Node.js 中使用 ECDSA 签名遇到的坑
文/Fenying最近有个朋友问我关于Node.js下使用ECDSA的问题,主要是使用Node.js的Crypto模块无法校验网络传输过来的签名结果。在踩坑无数后,终于搞清楚了原因。坑0x00:签名输出格式在排除了证书、消息不一致的可能之后,我开始对比使用Node.js签名的结果与网络传输过来的签
Stella981 Stella981
3年前
React项目中应对开发、测试、生产环境下使用不同全局常量的问题
在开发过程中,避免不了后端在开发、测试、生产环境不一致的情况,这不最近就遇到这样的问题:在开发和测试环境,后端需要一个参数比如:zonehk1,在生产环境中需要的参数又是zonehka,那么解决这种问题的方法也不是唯一的,这里只介绍一种通过配置文件完成的过程。我们在构建react项目时,会执行npmruneject,导出react脚手架
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
陈哥聊测试 陈哥聊测试
1年前
你在测试金字塔的哪一层(上)
在准备将软件上线到生产环境之前需要进行测试。随着软件测试方式日趋成熟,软件开发团队的测试也在取代大量手动测试,逐渐实现自动化测试。
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(