你的浏览器无法正常显示内容,请更换或升级浏览器!

Node.js 内存泄漏排查实战:从堆内存暴涨到定位根因

tenfei
tenfei
发布于2026-08-09 11:06 阅读5次
Node.js 内存泄漏排查实战:从堆内存暴涨到定位根因
Node.js 服务内存暴涨导致 OOM 重启?本文记录一次真实的内存泄漏排查全过程:从监控报警、堆快照对比到定位闭包引用导致的缓存泄漏根因,并给出修复方案与日常避坑清单,适合 Node.js 后端开发者参考。
# Node.js 内存泄漏排查实战:从堆内存暴涨到定位根因 ## 一、事故背景 线上 Node.js 服务稳定运行两周后,监控系统报警:进程 RSS 内存从 300MB 一路涨到 2.1GB,容器多次因 OOM 被重启。服务没有明显的流量增长,GC 日志显示老年代持续攀升且回收不掉,基本可以断定存在内存泄漏。 ## 二、初步排查:确认泄漏方向 1. 查看进程内存分布,确认 heapUsed 占大头; 2. 连续抓取三次 heap dump,间隔 30 分钟; 3. 对比快照发现某个业务对象实例数量线性增长,与请求量成正比,锁定泄漏源在业务代码而非底层依赖。 ## 三、定位根因:经典的闭包引用 通过 Chrome DevTools 的 Comparison 视图对比快照,发现 MemoryLeakService 的实例被一个全局缓存 Map 持有,而缓存的值是闭包函数,闭包又引用了完整的业务对象上下文,导致每次请求产生的临时对象都无法被回收。本质上是「缓存了不该缓存的东西」。 ## 四、修复与验证 修复方案:缓存只保存必要字段,禁止保存闭包;同时为缓存增加 TTL 和最大容量限制,超出后按 LRU 淘汰。上线后连续观察一周,堆内存稳定在 350MB 左右,GC 恢复正常,问题彻底解决。 ## 五、避坑指南 - 慎用全局变量和模块级缓存,持有大对象时要考虑生命周期; - 定时器、事件监听器使用后必须清理,防止句柄堆积; - 每次发版前跑一遍内存基线测试,用 --max-old-space-size 限制堆上限,配合 heap dump 对比工具形成常态化检查机制; - 遇到内存问题优先看快照对比,别靠猜。

2

0

文章点评
Copyright © from 2021 by namoer.com
458815@qq.com QQ:458815
蜀ICP备2022020274号-2