搞定了 NodeJS 程序占内存多的问题

2019-01-04 09:42:40 +08:00
 kernel
去年转到 node 后发现真香,所有的微服务全都用 node 写了,然后马上发现了一个问题,之前 python 写的程序第 1 天和每 1000 天运行的内存都是一样的,而 node 程序会比较快地增长,直到 boom。

后来发现是因为 node 默认内存限制 1.7G ,而我的小机全是 1G - 2G 的,内存不足。
Google 了一翻,加上命令行选项

--max_old_space_size=600 --max_semi_space_size=8

发现有很大缓解,boom 的次数很少了,但是有另一个问题,就是运行二天后 node 内存就占了 600 - 800M 左右,但是没 Google 到别的解法,就这样将就了一年。

前几天翻 github 时发现另一个解法,在前面选项的基础上再替换默认内存分配器,用 jemalloc。

debian 上是

apt install libjemalloc-dev

然后运行 node 前
export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1

我是用 systemd 的,service 文件里加一行
Environment=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1
就行。

然后运行了三天,以前会占用 700M 内存的程序目前稳定在 120M 了,和以前 python 类似。
13843 次点击
所在节点    Node.js
14 条回复
yimity
2019-01-04 10:09:25 +08:00
这个是为啥呢?
zy445566
2019-01-04 10:19:46 +08:00
你的 node 是什么版本的,是否使用了 buffer,之前听说 node 修复了一个 buffer 导致内存泄露的 BUG
kernel
2019-01-04 10:24:06 +08:00
@zy445566 不是,各种版本都一样,目前混用 9 lts 和 10lts
kernel
2019-01-04 10:28:21 +08:00
@yimity 感觉就是不会主动释放空闲内存回 OS,会慢慢占满你指定的 max_old_space_size。
zy445566
2019-01-04 10:29:35 +08:00
真的很神奇,但你这个是典型的内存泄露,居然可以通过改 jemalloc 化解,真想知道原因
kernel
2019-01-04 10:34:15 +08:00
@zy445566 不是内存泄露,我写了好多 node 微服务,全这样,这特么不是我的锅吧
(因为有一个还特简单,不到 100 行,就是转一下图片格式)

另外你 google 一下,小内存机子运行 node 全是这问题, 参考
https://github.com/damianmr/heroku-node-settings
libook
2019-01-08 11:49:31 +08:00
用了五年 Node 了,只有最开始的两年遇到过 Node 内存泄露的问题,当时是定时重启,后来到了 Node6 好像就没有遇到过内存泄漏问题了,阿里云几十台 1 核 2G 的机器,分布式部署一个程序稳定运行数周,内存正常。。。

如果你用 Debian 的目前稳定版的话,我看到 nodejs 包依赖了 libc (其实就是 glibc ):
https://packages.debian.org/stretch/nodejs

或者你用 n、nvm 之类的安装 Node,不清楚是不是会直接用系统内预装的 glibc ?

所以会不会是你装的多数版本的 Node 都是共用的某一个版本的 glibc 提供的内存分配器,而这个版本内存分配器有内存泄漏问题,所以导致不管哪个版本的 Node 都有这个问题。。。实际上你的试验只控制了内存分配器这一个变数,所以基本能得出这个结论。

所以如果有时间可以尝试一下升级系统内的内存分配器动态链接库的版本,看看是不是也能解决这个问题?或者看看默认内存分配器的 issue 或 changelog 是否有提到相关内存泄露问题。
kernel
2019-01-08 12:20:17 +08:00
@libook 之前加了 max_old_space_size 后内存占用大,但是到那个限制后就不再增加了,程序也不崩,应该不是内存泄漏问题。jemalloc 看一些文章说明它是有缓解内存碎片减少 RSS 的作用。
zy445566
2019-01-10 17:48:04 +08:00
@kernel
巧了,三天前我也是这么猜测的
https://cnodejs.org/topic/5c300bf15bf06c5e7e3f17d7#5c330ce13898674067a7c19a
说不定真可以试一下升级内置的内存动态分配器
zy445566
2019-01-10 17:54:10 +08:00
@kernel
老哥,说真的,真希望你能研究一下,然后公开一下研究成果。
我手上没你的代码资源和机子的环境,我这边死都复现不了,纠结死了。
haohello
2019-01-16 15:13:07 +08:00
@kernel 你可以看看朴灵写的《深入浅出 nodejs 》,这本书虽然出了都好几年了,但是原理性的内容却是市面上唯一讲到的,里面有专门一节讲述 node 内存的一章,你所提到的内存限制其实都是 v8 对于 js 对象的大小限制,可以多用用 buffer, stream 这些。
zzwwjjdj319
2019-01-31 14:14:18 +08:00
为什么我的一直都是 70 多 MB,没出现过你说的几百 M 的
maxsky
2019-05-17 16:24:24 +08:00
我也一直 600+M,CentOS 7 和 macOS 都是,分别 Node 10 与 12 版本,两个系统都试了下启动 Node 前 export LD_PRELOAD 并指定 jemalloc,内存依旧...会不会是 Node 版本原因
toma77
2020-03-24 10:55:14 +08:00
@maxsky
我跟你一样的情况,你问你后面怎么解决的呢?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/523721

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX