Node.JS内存泄漏PM2

maj*_*rif 7 memory-leaks node.js

我正在运行我的服务器,pm2 start ...并在2小时后pm2 monit向我展示3GB memory.所以我附上了记忆,现在我再等了2个小时,再次显示pm2 monit到达的记忆3GB.

所以,我检查了生成的日志memwatch.给我看了:

{ before: { nodes: 75659, size_bytes: 11141702, size: '10.63 mb' },
  after: { nodes: 73226, size_bytes: 10840598, size: '10.34 mb' },
  change:
   { size_bytes: -301104,
     size: '-294.05 kb',
     freed_nodes: 5141,
     allocated_nodes: 2708,
Run Code Online (Sandbox Code Playgroud)

而另一个:

{ before: { nodes: 72591, size_bytes: 10728318, size: '10.23 mb' },
  after: { nodes: 73284, size_bytes: 10798062, size: '10.3 mb' },
  change:
   { size_bytes: 69744,
     size: '68.11 kb',
     freed_nodes: 5931,
     allocated_nodes: 6620,
Run Code Online (Sandbox Code Playgroud)

现在我真的很困惑,那些是最后的日志,所以我很确定这些是pm2 monit显示巨大的内存泄漏时生成的日志.

那么,为什么要向memwatch我展示10MB+内存和pm2 monit显示3GB+


现在切换到类似forevermonit的东西,看看泄漏是否仍然存在.


多一点背景

  • 我一直试图剖析并发现泄漏,并且在型材上没有任何泄漏.
  • 当客户端连接时启动memwatch diff,并在客户端断开连接时进行区分.

小智 6

在这个线程上有很多非常糟糕的答案。真的,真的很糟糕。

答案很简单:您的代码存在需要查找和删除的内存泄漏,而且 GC 错误的可能性很小,您的代码更有可能是罪魁祸首。

所以首先:

  1. 我发现使用 PM2 时垃圾收集器不起作用” - 这显然是荒谬的,PM2 运行 node,它使用 V8,它内置了自己的垃圾收集器。这不会因为您运行 PM2 而被禁用。
  2. 所以在修复之前调用 GC ” - 不!如果您的代码有泄漏,手动调用 GC 是很懒惰的,您应该修复它们。
  3. 在删除 pm2 之后,现在不再有内存泄漏。 ” - 不,您只是没有在 PM2 中监视它;泄漏仍然存在,您只是看不到错误,因为您正在使用 node 运行它而不查看结果。

其次,实际的解决方案应该是:

使用您选择的工具分析您的代码的内存和 CPU 使用情况。对于大多数人来说,这将是连接到正在运行的节点实例的 Chrome 调试工具,并查看哪些函数导致内存使用量激增。简单地手动调用 GC 是很懒惰的,因为您的代码仍然存在泄漏,但您只是告诉 V8 在您的应用程序泄漏后不断地吸纳内存,这是非常懒惰的做法。

  • 我可以证明这一点。我在开发工具中检查了我的应用程序,发现没有泄漏。放置了几个小时,仍然没有泄漏。我在pm2中跑了一下,内存一直在缓慢上升。然后,我将所有内存囤积变量和函数设置为 null,运行节点(导入除外),否则它应该囤积 0 字节。在开发工具中,没问题。在pm2?瞧!泄露。pm2 肯定有问题 (4认同)
  • 超级简化的代码证明了代码没有泄漏,因为在没有 pm2 的情况下执行时没有泄漏。这个问题已经5年了,现在肯定已经解决了。 (2认同)
  • 我观察到与其他人相同的行为 - 当我仅使用 Node 启动脚本时,它保留了大约 30-50MB 的内存。当我使用 PM2 启动它时,PM2 最初报告 70MB,然后慢慢增长。我不知道这是 PM2 的问题还是我使用它的方式的问题,但它看起来不像是正在运行的脚本的问题。哦,内存分析器没有显示任何变化 - 即使我运行 PM2,当我将分析器附加到子进程时,它显示 35-40MB,而 PM2 显示 240。 (2认同)

Vin*_*cha 3

  • 我也面临着同样的问题,但经过一番研究后我发现nodejs在使用pm2时没有调用垃圾收集器。
  • 因此,在 PM2 修复该问题之前,临时解决方法是强制调用垃圾收集器,使用以下方法

pm2 启动 app.js --node-args='--expose-gc'

上面的参数--expose-gc将允许我们从 Node js 强制调用垃圾收集器,现在使用以下代码强制车库收集。

if (global.gc) {
   global.gc();
} else {
   console.log('Garbage collection unavailable.  use --expose-gc '
   + 'when launching node to enable forced garbage collection.');
}  
Run Code Online (Sandbox Code Playgroud)

这将解决 PM2 内存泄漏问题。

  • 你能提供“但经过一番研究后我发现nodejs在使用pm2时没有调用垃圾收集器。”的来源吗?谢谢。 (14认同)