Node.js和碎片

时间:2016-11-08 19:10:48

标签: javascript node.js memory-management garbage-collection v8

背景:我来自Microsoft世界,我过去常常将网站存储在IIS上。经验教会我每天回收一次应用程序池,以消除由于碎片造成的奇怪问题。回收应用程序池基本上意味着重新启动应用程序而无需重新启动整个IIS。我还观看了一个演讲,解释了微软如何在.Net 4.5中减少碎片。

现在,我将Node.js应用程序部署到生产环境中,我必须确保它始终完美无缺。我本来想让我的应用程序每天重启一次。然后我做了一些研究,以便找到一些关于Node.js中碎片问题的线索。我发现的唯一一件事是来自an article describing GC in V8的段落:

  

确保快速对象分配,短暂的垃圾收集暂停,以及   “没有内存碎片V8”采用了一个世界,   世代的,准确的,垃圾收集器。

这句话真的不足以让我放弃为我的应用程序构建重启机制,但另一方面,如果没有问题,我不想做一些工作。

所以我的问题是:

我应该或不应该不时地重启我的应用程序以防止碎片化?

3 个答案:

答案 0 :(得分:11)

在知道内存消耗确实存在问题之前实现服务器重启是一种过早的优化。因此,在你真正发现它是一个问题之前,我认为你不应该这样做。您可能会发现要优化的更重要问题,而不是内存消耗。

要确定您是否需要重新启动服务器,我建议您执行以下操作:

  1. 设置一些监控工具,例如https://newrelic.com/,让您监控自己的表现。
  2. 持续监控记忆。尝试查看内存消耗量是否稳定增加,或者是否达到平衡。
  3. 在您需要采取行动之前确定可接受的阈值。例如,一旦您的应用程序占用系统内存的60%,您需要开始考虑重新启动服务器并确定重新启动时间间隔。
  4. 决定是否可以在重新启动服务器时“停机”。如果您不想要停机,则可能需要构建代理层来引导流量。
  5. 通常,我建议为所有动态垃圾收集语言重新启动服务器。这在那些类型的大型应用程序中相当常见。几乎不可避免的是,代码库中的某个小错误,或者您依赖的某个库会泄漏内存。即使您修复了一个泄漏,最终也会得到另一个泄漏。这可能会使您的团队感到沮丧,这将基本上导致服务器重启策略,并定义应用程序的内存消耗可接受的内容。

答案 1 :(得分:3)

我同意@Parris。您应该首先确定是否确实需要重新启动策略。我建议使用pm2 docs here。即使您不想注册keymetrics,它也是一个非常好的小流程管理器,并且可以快速设置。您可以从命令行获取内存使用情况的报告。看起来像这样。

pm2 output

此外,如果你在上面的群集模式下启动,你可以调用pm2 restart my_app,第一个可能会在最后一个离线之前再次启动(这是一个额外的好处,这是一个真正的原因8个过程是利用所有8个核心)。如果您对停机时间表示坚持,可以按照id。

逐步重新启动它们

答案 2 :(得分:2)

我同意@Parris这似乎是一个不成熟的优化。此外,重新启动不是解决潜在问题的方法,而是治疗症状。

如果内存错误是您的节点应用程序的一个普遍问题,那么我认为有些人想到为什么在您的程序中首先出现这种碎片可能是一项有价值的工作。理解为什么在程序运行很长一段时间后发生内存错误,并重构程序的体系结构以解决问题的根源,在我眼中比在解决症状时更好的解决方案。

我相信有两件事会对你有所帮助。

  1. immutable objects会有很大帮助,它们比使用可变对象更容易预测,并且不受项目生效时间的影响。此外,由于不可变对象是只读存储器块,因此它们比可变对象更快,服务器必须花费资源来决定是否读取或写入存储对象的存储块。我目前使用名为IMMUTABLE的库,它对我很有用。还有其他人也喜欢Deep Freeze,但我从未使用它。

  2. 确保正确管理您的应用程序进程,内存泄漏是我遇到此问题的第二大问题。同样,这可以通过考虑应用程序的结构以及如何处理用户事件来解决,确保一旦客户端没有使用某个进程从heap正确删除它,如果不是然后heap一直在增长,直到消耗掉所有内存导致应用程序崩溃(请参阅下图以查看V8的内存方案,以及heap所在的位置)。 Node是一个C ++程序,它由谷歌的V8和Javascript控制。

  3. V8 memory Scheme

    您可以使用Node.js的process.memoryUsage()来监控内存使用情况。当您确定如何管理堆时,V8提供了两种解决方案,一种是Scavenge,它非常快,但不完整。另一种是Mark-Sweep,它很慢并释放所有未引用的内存。

    有关如何在运行Node.js的V8上管理堆和管理内存的详细信息,请参阅this博客文章

    因此,实施的负责任的方法是密切关注开放流程,深入理解heap,以及如何释放未引用的内存块。考虑到这一点创建项目也会使项目更具可扩展性。