为什么节点 16 内存中存储的字符串没有发生垃圾收集?

问题描述 投票:0回答:1

我的

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 页面。

有人可以帮忙解决这个问题吗?

javascript node.js reactjs garbage-collection v8
1个回答
0
投票

首先,您知道如何获取和查看 Node.js 的堆快照 - 这很棒。不过有一个小细节:

测试完成后,让它闲置以进行垃圾收集,然后再次拍摄另一个堆快照

无需等待,拍摄堆快照时垃圾收集会自动发生。快照仅包含活动对象,没有垃圾。

在您的情况下,很明显内存泄漏,因为 HTML 响应页面以某种方式累积在内存中。如何证明这一点:

  • 启动服务器
  • 监控内存中
    "<!DOCTYPE HTML>..."
    字符串的数量,例如通过堆快照或通过 DevTools 中的 queryObjects 命令
  • 随着处理的用户请求越来越多,金额应该会增加

您的下一步是分析此快照。

选择第一个泄漏字符串并查看其保留树。对接下来的几个字符串重复此操作。您需要找到一些对象,该对象本身保存对 HTML 字符串的引用,可能是通过一长串中间对象。这可能是基于 Map 构建的内存缓存,或者是服务器请求/响应的集合,或者是在每个请求上创建的函数的闭包,甚至是第三方。浏览所有泄漏的字符串,您不可避免地会注意到保留树中的一些重复模式,并了解谁以及为什么将这些对象保存在内存中。

您可以首先使用内存泄漏的实例进行训练

© www.soinside.com 2019 - 2024. All rights reserved.