Node.js 和碎片化
Node.js and fragmentation
背景: 我来自微软世界,以前我的网站都存储在IIS上。经验告诉我每天回收我的应用程序池一次,以消除由于碎片造成的奇怪问题。回收应用程序池基本上意味着在不重新启动整个 IIS 的情况下重新启动您的应用程序。我还看了一个讲座,解释了 Microsoft 如何在 .Net 4.5 中大量减少碎片。
现在,我正在将 Node.js 应用程序部署到生产环境,我必须确保它始终完美运行。我最初想让我的应用程序每天重新启动一次。然后我做了一些研究,以便在 Node.js 中找到一些关于碎片问题的线索。我唯一找到的是 an article describing GC in V8:
中的一段片段
To ensure fast object allocation, short garbage collection pauses, and
the “no memory fragmentation V8” employs a stop-the-world,
generational, accurate, garbage collector.
这种说法确实不足以让我放弃为我的应用程序构建重启机制,但另一方面我不想做一些没有问题的工作。
所以我的问题是:
我是否应该时不时地重启我的应用程序以防止碎片化?
在您知道内存消耗确实是一个问题之前实施服务器重启是过早的优化。因此,我认为在您真正发现这是一个问题之前,您不应该这样做。您可能会发现与内存消耗相比更重要的问题需要优化。
要确定是否需要重启服务器,我建议您执行以下操作:
- 设置一些监控工具,例如 https://newrelic.com/,让我们监控您的表现。
- 持续监控您的记忆力。尝试查看消耗的内存量是否稳定增加,或者是否趋于平稳。
- 在你需要采取行动之前确定一个可接受的阈值。例如,一旦您的应用消耗了 60% 的系统内存,您就需要开始考虑重启服务器并决定重启间隔。
- 确定您是否可以在重新启动服务器时使用 "downtime"。如果你不想停机,你可能需要构建一个代理层来引导流量。
一般来说,我建议为所有动态的、垃圾收集的语言重新启动服务器。这在那些类型的大型应用程序中相当常见。几乎不可避免的是,您的代码库或您所依赖的库中某个地方的某个小错误会泄漏内存。即使你修复了一个漏洞,你最终也会得到另一个漏洞。这可能会让您的团队感到沮丧,这基本上会导致服务器重启策略,以及关于您的应用程序内存消耗可接受的定义。
我同意@Parris。您可能应该先弄清楚您是否真的需要重新启动策略。我建议使用 pm2 docs here。即使您不想注册关键指标,它也是一个相当不错的小流程管理器,而且设置起来非常快。您可以从命令行获取内存使用情况报告。看起来像这样。
此外,如果你像上面那样以集群模式启动,你可以调用 pm2 restart my_app
并且第一个可能会在最后一个离线之前再次启动(这是一个额外的好处,真正的原因拥有 8 个进程就是利用所有 8 个核心)。如果你坚持不停机,你可以根据 id 1 1 重启它们。
我同意@Parris 的观点,这似乎是一个过早的优化。另外,重启不是解决根本问题的办法,而是治标不治本。
如果内存错误是您的节点应用程序的普遍问题,那么我认为首先考虑为什么在您的程序中出现这种碎片可能是一项有价值的工作。在我看来,理解程序运行 运行 很长一段时间后为什么会出现内存错误,并重构程序的体系结构以解决问题的根源,是比仅解决症状更好的解决方案。
我相信有两件事会让你受益。
immutable objects will help a lot, they are a lot more predictable than using mutable objects, and will not be affected by the length of time the project has been live. Also, since immutable objects are read only blocks of memory they are faster than mutable objects which the server has to spend resources deciding whether to read, or write on the memory block which stores the object. I currently use the library called IMMUTABLE and it works well for me. There are other one's as well like Deep Freeze,不过我没用过
确保正确管理应用程序的进程,内存泄漏是我遇到的导致此问题的第二大因素。同样,这可以通过考虑您的应用程序的结构以及用户事件的处理方式来解决,确保一旦客户端未使用某个进程,就将其从 heap
中正确删除,如果不是然后 heap
不断增长,直到所有内存都被消耗,导致应用程序崩溃(请参阅下图以查看 V8 的内存方案,以及 heap
所在的位置)。 Node 是一个 C++ 程序,它由 Google 的 V8 和 Javascript 控制。
您可以使用 Node.js 的 process.memoryUsage()
来监控内存使用情况。当您确定如何管理您的堆时,V8 提供了两种解决方案,一种是 Scavenge,它非常快速,但不完整。另一个是 Mark-Sweep,它很慢并且会释放所有未引用的内存。
请参阅 this 博客 post 了解有关如何在运行 Node.js
的 V8 上管理堆和内存的更多信息
因此,负责任的实施方法是密切关注打开的进程,深入了解 heap
,以及如何释放未引用的内存块。在创建项目时考虑到这一点也会使项目更具可扩展性。
背景: 我来自微软世界,以前我的网站都存储在IIS上。经验告诉我每天回收我的应用程序池一次,以消除由于碎片造成的奇怪问题。回收应用程序池基本上意味着在不重新启动整个 IIS 的情况下重新启动您的应用程序。我还看了一个讲座,解释了 Microsoft 如何在 .Net 4.5 中大量减少碎片。
现在,我正在将 Node.js 应用程序部署到生产环境,我必须确保它始终完美运行。我最初想让我的应用程序每天重新启动一次。然后我做了一些研究,以便在 Node.js 中找到一些关于碎片问题的线索。我唯一找到的是 an article describing GC in V8:
中的一段片段To ensure fast object allocation, short garbage collection pauses, and the “no memory fragmentation V8” employs a stop-the-world, generational, accurate, garbage collector.
这种说法确实不足以让我放弃为我的应用程序构建重启机制,但另一方面我不想做一些没有问题的工作。
所以我的问题是:
我是否应该时不时地重启我的应用程序以防止碎片化?
在您知道内存消耗确实是一个问题之前实施服务器重启是过早的优化。因此,我认为在您真正发现这是一个问题之前,您不应该这样做。您可能会发现与内存消耗相比更重要的问题需要优化。
要确定是否需要重启服务器,我建议您执行以下操作:
- 设置一些监控工具,例如 https://newrelic.com/,让我们监控您的表现。
- 持续监控您的记忆力。尝试查看消耗的内存量是否稳定增加,或者是否趋于平稳。
- 在你需要采取行动之前确定一个可接受的阈值。例如,一旦您的应用消耗了 60% 的系统内存,您就需要开始考虑重启服务器并决定重启间隔。
- 确定您是否可以在重新启动服务器时使用 "downtime"。如果你不想停机,你可能需要构建一个代理层来引导流量。
一般来说,我建议为所有动态的、垃圾收集的语言重新启动服务器。这在那些类型的大型应用程序中相当常见。几乎不可避免的是,您的代码库或您所依赖的库中某个地方的某个小错误会泄漏内存。即使你修复了一个漏洞,你最终也会得到另一个漏洞。这可能会让您的团队感到沮丧,这基本上会导致服务器重启策略,以及关于您的应用程序内存消耗可接受的定义。
我同意@Parris。您可能应该先弄清楚您是否真的需要重新启动策略。我建议使用 pm2 docs here。即使您不想注册关键指标,它也是一个相当不错的小流程管理器,而且设置起来非常快。您可以从命令行获取内存使用情况报告。看起来像这样。
此外,如果你像上面那样以集群模式启动,你可以调用 pm2 restart my_app
并且第一个可能会在最后一个离线之前再次启动(这是一个额外的好处,真正的原因拥有 8 个进程就是利用所有 8 个核心)。如果你坚持不停机,你可以根据 id 1 1 重启它们。
我同意@Parris 的观点,这似乎是一个过早的优化。另外,重启不是解决根本问题的办法,而是治标不治本。
如果内存错误是您的节点应用程序的普遍问题,那么我认为首先考虑为什么在您的程序中出现这种碎片可能是一项有价值的工作。在我看来,理解程序运行 运行 很长一段时间后为什么会出现内存错误,并重构程序的体系结构以解决问题的根源,是比仅解决症状更好的解决方案。
我相信有两件事会让你受益。
immutable objects will help a lot, they are a lot more predictable than using mutable objects, and will not be affected by the length of time the project has been live. Also, since immutable objects are read only blocks of memory they are faster than mutable objects which the server has to spend resources deciding whether to read, or write on the memory block which stores the object. I currently use the library called IMMUTABLE and it works well for me. There are other one's as well like Deep Freeze,不过我没用过
确保正确管理应用程序的进程,内存泄漏是我遇到的导致此问题的第二大因素。同样,这可以通过考虑您的应用程序的结构以及用户事件的处理方式来解决,确保一旦客户端未使用某个进程,就将其从
heap
中正确删除,如果不是然后heap
不断增长,直到所有内存都被消耗,导致应用程序崩溃(请参阅下图以查看 V8 的内存方案,以及heap
所在的位置)。 Node 是一个 C++ 程序,它由 Google 的 V8 和 Javascript 控制。
您可以使用 Node.js 的 process.memoryUsage()
来监控内存使用情况。当您确定如何管理您的堆时,V8 提供了两种解决方案,一种是 Scavenge,它非常快速,但不完整。另一个是 Mark-Sweep,它很慢并且会释放所有未引用的内存。
请参阅 this 博客 post 了解有关如何在运行 Node.js
的 V8 上管理堆和内存的更多信息因此,负责任的实施方法是密切关注打开的进程,深入了解 heap
,以及如何释放未引用的内存块。在创建项目时考虑到这一点也会使项目更具可扩展性。