Node 内存泄漏排查案例
背景
在阿里云上看到我运行了一段时间的程序,发现 memory 一项基本是在稳步提升,就知道有内存泄漏的情况出现。如下图

近三日从 35% 升到 40%,缓慢而坚定的提升。
代码
排查此问题需要分析其堆内存快照,当然我们不能直接使用线上机器调试。不幸的是测服机器在内网,和阿里云联不通,alinode 发挥不了作用。但所幸的是 V8 引擎提供了内部接口可以直接把堆中的JS对象导出来供开发者分析。我们采用heapdump这个模块,执行如下命令安装
$ npm install heapdump --save
"heapdump": "^0.3.15",
执行如下
const heapdump = require('heapdump');
heapdump.writeSnapshot(`./${Date.now()}.heapsnapshot`);
生成的文件如下
$ ll -lh
-rw-rw-r-- 1 souche souche 38M Nov 19 19:00 1574161221512.heapsnapshot
总之我在测服上定时每 2 小时打印堆栈快照。
总之,你可以使用 scp 命令把测服的代码导出到本地
# 传递单个文件
$ scp 【服务器用户名】@【服务器地址】:【服务器上存放文件的路径】【本地文件的路径】
# 例如
$ scp souche@172.11.xxx.xxx:/home/souche/app/egg-test/current/1574161221512.heapsnapshot /Users/dasouche/workspace/sc-node
# 传递文件夹
scp -r 【服务器用户名】@【服务器地址】:【服务器上存放文件的路径】【本地文件的路径】
分析步骤
打开 chrome-控制台-Memory-load

加载完后得到

简而言之,Shallow Size 就是对象自身被创建时所需要内存的大小,Retained Size 就是当把对象从支配树上拿掉,对象和它的下级节点一共能释放的内存大小。
其术语简介可参见:https://developers.google.com/web/tools/chrome-devtools/memory-problems/memory-101
分析过程
从线上机器导出两个堆文件,一个是10月30日打印的,一个是11月4日打印的,其内存上升了 100+ MB。
比对两个堆,把第二个堆文件的 Summary 切换成 Comparison,并按 Delta 倒叙排,发现增长最快的是 (concatenated string) 。其中有很多连接字符串,其中有大量的sql语句,并且有大量的schedule执行。

(constructor) 增长排第二,其中也见到不少 schedule,那我们可以确认就是 noticeJob.ts 这个定时器的问题。

本项目使用了 egg 作为框架,schedule 就是指定时触发的逻辑。联系代码我们发现在一个 5 秒触发一次的 schedule 里,里面不停的触发队列的 process 监听事件,猜测是 Queue.process 监听事件越绑越多的毛病,也导致里面的逻辑越触发越多。
这其实就是队列绑定监听事件的误用了。
// app/schedule/noticeJob.ts
'use strict';
import { Context } from 'egg';
import * as kue from 'kue';
module.exports = {
schedule: {
disable: false,
// 每五秒触发一次
cron: '*/5 * * * * *',
immediate: true,
type: 'worker',
},
async task(ctx: Context) {
const Queue = ctx.app.kue;
Queue.process('noticeCalling', async function(job, done) {
const { uid, rid, subId } = job.data;
await ctx.service.message.noticedCalling(uid, rid);
// done();
});
},
};
我们在测服注释掉这段定时器后,每隔一小时打印一次(因为测服无法连阿里云),观察一天,内存没有上升趋势,这很好。
-rw-rw-r-- 1 souche souche 38M Nov 24 11:24 1574565877609.heapsnapshot
-rw-rw-r-- 1 souche souche 37M Nov 24 12:24 1574569477611.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 24 13:24 1574573077611.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 24 14:24 1574576677613.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 24 15:24 1574580277614.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 24 16:24 1574583877614.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 24 17:24 1574587477616.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 24 18:24 1574591077616.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 24 19:24 1574594677616.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 24 20:24 1574598277618.heapsnapshot
-rw-rw-r-- 1 souche souche 37M Nov 24 21:24 1574601877620.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 24 22:24 1574605477621.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 24 23:24 1574609077622.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 25 00:24 1574612677622.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 25 01:24 1574616277622.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 25 02:24 1574619877623.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 25 03:24 1574623477624.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 25 04:24 1574627077626.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 25 05:24 1574630677627.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 25 06:24 1574634277627.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 25 07:24 1574637877628.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 25 08:24 1574641477629.heapsnapshot
-rw-rw-r-- 1 souche souche 38M Nov 25 09:24 1574645077630.heapsnapshot
-rw-rw-r-- 1 souche souche 39M Nov 25 10:24 1574648677630.heapsnapshot
-rw-rw-r-- 1 souche souche 39M Nov 25 11:24 1574652277632.heapsnapshot
解决方法
最后就在 app.ts 设置这个 process 的监听,移除 schedule 里的定时脚本
Node 内存泄漏排查案例的更多相关文章
- 轻松排查线上Node内存泄漏问题
I. 三种比较典型的内存泄漏 一. 闭包引用导致的泄漏 这段代码已经在很多讲解内存泄漏的地方引用了,非常经典,所以拿出来作为第一个例子,以下是泄漏代码: 'use strict'; const exp ...
- Chrome JS内存泄漏排查方法(Chrome Profiles)
原文网址:http://blog.csdn.net/kaitiren/article/details/19974269 JS内存泄漏排查方法(Chrome Profiles) Google Ch ...
- windows 下面的内存泄漏排查.
内存泄漏排查 一下本人只是简单的介绍一个实用, 如果读者很感兴趣, 可以查阅msdn自己去深入调查相关的API和原理. API 介绍 1. 马上打印泄漏信息:_CrtDumpMemoryLeaks() ...
- Java内存泄漏真实案例
内存泄漏:当不再需要一个对象时,垃圾收集器会回收它:如果不需要的对象一直在产生而不被收回,就称作“内存泄漏”. 以下为本人在工作中遇到的内存泄漏的案例: 1.对于大量的请求,使用了Executors. ...
- 填坑总结:python内存泄漏排查小技巧
摘要:最近服务遇到了内存泄漏问题,运维同学紧急呼叫解决,于是在解决问题之余也系统记录了下内存泄漏问题的常见解决思路. 本文分享自华为云社区<python内存泄漏排查小技巧>,作者:luti ...
- Netty堆外内存泄漏排查,这一篇全讲清楚了
上篇文章介绍了Netty内存模型原理,由于Netty在使用不当会导致堆外内存泄漏,网上关于这方面的资料比较少,所以写下这篇文章,专门介绍排查Netty堆外内存相关的知识点,诊断工具,以及排查思路提供参 ...
- JS内存泄漏排查方法——Chrome Profiles
一.概述 Google Chrome浏览器提供了非常强大的JS调试工具,Heap Profiling便是其中一个.Heap Profiling可以记录当前的堆内存(heap)快照,并生成对象的描述文件 ...
- 内存泄漏学习案例-1-ArrayList
解决 内存泄漏 于是赶快登陆探测服务器,首先是 top free df 三连,结果还真发现了些异常. 我们的探测进程 CPU 占用率特别高,达到了 900%. 我们的 Java 进程,并不做大量 CP ...
- Spring Boot引起的“堆外内存泄漏”排查及经验总结
小结: 检索词:C++内存分配器.jvm内存模型.gdb.内存泄露 https://tech.meituan.com/2019/01/03/spring-boot-native-memory-leak ...
随机推荐
- python3(十三)map reduce
# map()函数接收两个参数,一个是函数,一个是Iterable, # map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回. def f(x): return x * ...
- GitHub搭建个人主页
GitHub搭建个人主页 1.注册登录GitHub 2.新建仓库 新建一个名为"username.github.io",其中username为你的用户名,仓库必须为公有类型,私有仓 ...
- 简单完成Excel导出
Excel的导出只需要三步即可完成: 1,完成excel的工具类编写,直接复制即可 package cn.com.bcl.util; import java.util.List; import org ...
- 学习笔记分享之汇编---3. 堆栈&标志寄存器
前言: 此文章收录在本人的<学习笔记分享>分类中,此分类记录本人的学习心得体会,现全部分享出来希望和大家共同交流学习成长.附上分类链接: https://www.cnblogs.c ...
- Salesforce考试 | 如何维护我的Salesforce认证
问题1 Salesforce证书是需要每年维护吗? Salesforce每年会发布3次Realese,分别是Spring.Summer和Winter,可以理解为一年3次的系统新版本更新,每次Relea ...
- Nightmare BFS
Ignatius had a nightmare last night. He found himself in a labyrinth with a time bomb on him. The la ...
- 性能测试-pidstat 问题定位分析
pidstat 概述 pidstat是sysstat工具的一个命令,用于监控全部或指定进程的cpu.内存.线程.设备IO等系统资源的占用情况.pidstat首次运行时显示自系统启动开始的各项统计信息, ...
- mac上搭建mysql环境配置和Navicat连接mysql
mac上搭建mysql环境配置 1.下载mysql for mac: https://downloads.mysql.com/archives/community/ 注意:mysql版本要和你的MAC ...
- BUUOJ [极客大挑战 2019]Secret File
[极客大挑战 2019]Secret File 0X01考点 php的file伪协议读取文件 ?file=php://filter/convert.base64-encode/resource= 0X ...
- 进阶 Linux基本命令-2
mkdir -p /a/b/c/d -p 循环创建目录yum install tree -y ...