我的
node.js
应用程序存在内存泄漏,导致 Pod 崩溃。我注意到并发命中时内存激增,并且垃圾收集发生到一定程度,但在理想情况下,内存不会恢复到之前的水平。然而,内存泄漏很小,大约需要 72 小时 Pod 才会崩溃,当达到 1.1 GB
时就会发生这种情况。理想情况下,内存利用率不应超过 40MB
,在高峰时段激增是正常的,但在空闲时会恢复到 40MB
左右。
我们对
node version 12
没有任何此类问题,但对 node 16
我们面临内存泄漏问题。
我在开始测试之前拍摄了一个堆快照,测试完成后将其闲置以进行垃圾收集,然后再次拍摄另一个堆快照。
(string)
需要周围13988028
(compiled code)
需要周围12948428
测试之前,字符串中的数据是这样的
(string)
需要周围61617524
(compiled code)
需要周围67697612
编译后的代码还包含字符串的引用。
并且在测试之后,
HTML
页面内容被添加到没有被垃圾收集的字符串中。它还包含一些请求未成功的 500
错误响应 HTML 页面。
有人可以帮忙解决这个问题吗?
首先,您知道如何获取和查看 Node.js 的堆快照 - 这很棒。不过有一个小细节:
测试完成后,让它闲置以进行垃圾收集,然后再次拍摄另一个堆快照
无需等待,拍摄堆快照时垃圾收集会自动发生。快照仅包含活动对象,没有垃圾。
在您的情况下,很明显内存泄漏,因为 HTML 响应页面以某种方式累积在内存中。如何证明这一点:
"<!DOCTYPE HTML>..."
字符串的数量,例如通过堆快照或通过 DevTools 中的 queryObjects 命令您的下一步是分析此快照。
选择第一个泄漏字符串并查看其保留树。对接下来的几个字符串重复此操作。您需要找到一些对象,该对象本身保存对 HTML 字符串的引用,可能是通过一长串中间对象。这可能是基于 Map 构建的内存缓存,或者是服务器请求/响应的集合,或者是在每个请求上创建的函数的闭包,甚至是第三方库。浏览所有泄漏的字符串,您不可避免地会注意到保留树中的一些重复模式,并了解谁以及为什么将这些对象保存在内存中。
您可以首先使用内存泄漏的实例进行训练