Skip to content

Latest commit

 

History

History
47 lines (30 loc) · 2.52 KB

nodejs mem pitfalls.md

File metadata and controls

47 lines (30 loc) · 2.52 KB
date tags
2021-03-11
javascript

内存限制注意点

对于内存泄漏,一般来说是这样的步骤:

  1. 兜底方案,泄漏后重启实例,保证服务器配额健康。
  2. heapdump,分析具体泄漏原因。在兜底方案执行过频时,才需要紧急分析。

这里讲一下1。有两种常见的思路可以做到内存泄漏后重启:

  1. “自杀”,从实例内部监控,并且干掉自己。
  2. “他杀”,从实例外部监控进程,在实例超配额的时候干掉实例。

同样也有各自的手段,先说“自杀”,在nodejs中,可以用--max-old-space-size,当然也可以直接监控内存指标。“他杀”更依赖于实际的runtime,docker或者pm2,方式可能不一样。在pm2中有一个参数叫max_memory_restart,其他选型可能有其他选型的配置参数。max_memory_restart有两个官方没有说明的点:

  1. 整个一套服务的所有实例内存占用是max_memory_restart * 实例数
  2. max_memory_restart监控有30s的延迟,可以通过PM2_WORKER_INTERVAL环境变量修改。

所以在计算配额的时候,需要考虑实例数max-old-space-size也一样。并且因为延迟,所以针对内存的激增,pm2的反应是有些迟钝的,开发者需要评估是否需要调整监控的实时性,在实时性方面有可能“自杀”更好。实时性最好的应该是max-old-space-size,不过需要关注老生区与rss的差值是否过大,而导致整体配额估值不准。

worker的内存

对于worker的配额,计算也很简单:

  • 单个worker限制配额
  • 限制worker的个数

在node中,有两种不同的worker

  • 基于thread的
  • 基于process的

在内存方面,两者最大的区别是,worker_thread没有生成新的进程(不过有新的v8实例哈),rss是共通的。所以对于“他杀”形式的内存限制是一个利好,这样通过类似max_memory_restart的参数,可以直接掌控所有worker。如果是process_worker,又是另外一种情况,还需要具体分析。

对于thread和process两种worker,都可以指定v8的参数,不过如果在外部有“他杀”程序,自毁也只能算提高实时性了,没看到特别有优越性。

小结

  • 建议使用外部程序监控内存
    • 注意node实例数对内存配额计算的影响
    • 注意外部监控的延迟
    • 特别在意实时性可在内部监控,注意老生区监控可能导致的偏差
  • 建议使用thread_worker,共用process以达到rss统筹监控