如何获取运行 Node JS 应用程序的 k8s Pod 的当前和准确的内存使用情况
Posted
技术标签:
【中文标题】如何获取运行 Node JS 应用程序的 k8s Pod 的当前和准确的内存使用情况【英文标题】:How to get Current and accurate Memory Usage of k8s Pod running Node JS application 【发布时间】:2021-12-25 14:10:31 【问题描述】:我有一个在 k8s pod 上运行的 NodeJS 应用程序。 pod 的实际大小是 2GB,但在环境变量中,我们将此值设置为 4GB --max-old-space-size=4096
(在我的情况下这不是真的 - 对于某些租户,我们确实分配了 4GB,但大多数 pod 有 2GB)。
现在我尝试了 2 种方法来检测内存使用情况和总内存,两者都提供了不同的统计信息。
-
我正在从此系统文件中获取内存使用情况:
/sys/fs/cgroup/memory/memory.usage_in_bytes
和来自该文件的总内存:/sys/fs/cgroup/memory/memory.limit_in_bytes
limit_in_bytes
正确返回 2GB,但 usage_in_bytes
的值波动太大,几分钟内大约为 1GB,即使在那一分钟内没有任何变化(对系统没有压力),下一分钟会飙升至 2GB .
进程统计
Memory Usage POD: 2145124352
shlog - memLimit 214748364
我尝试的第二个选项是使用此 V8
内置节点 js 库来获取堆统计信息:https://nodejs.org/api/v8.html#v8getheapstatistics。
用法:
const initialStats = v8.getHeapStatistics();
console.log("heap_size_limit: ", (initialStats.heap_size_limit)); // total memory
console.log("total_heap_size: ", (initialStats.total_heap_size)); // current usage
现在在总内存中,它返回 4G,这在我的情况下是不正确的。但是这里的当前用法似乎很正确。
同一进程的统计数据
total_heap_size: 126312448,
heap_size_limit: 4320133120,
v8 getHeapStatistics 方法的完整响应:
HeapStats:
total_heap_size: 126312448,
total_heap_size_executable: 1097728,
total_physical_size: 124876920,
total_available_size: 4198923736,
used_heap_size: 121633632,
heap_size_limit: 4320133120,
malloced_memory: 73784,
peak_malloced_memory: 9831240,
does_zap_garbage: 0,
number_of_native_contexts: 1,
number_of_detached_contexts: 0
我的目标是根据 pod 的总内存来检测内存使用情况,因此当内存消耗达到 85% 时进行一些节流。我愿意使用第一种方法,但请告诉我为什么内存使用量差异如此之大,以及如何获得 pod 的准确内存使用情况。
真的很期待在这方面得到一些帮助。谢谢。
【问题讨论】:
这有帮助吗? ***.com/questions/48387040 这两个数字可能都是对的,但衡量的是不同的东西;查看v8
文档,我可能希望total_physical_size
或malloced_memory
更接近cgroups 分配统计信息。您是专门尝试测量节点堆内存(与节点可能分配的其他内存不同),还是只是进行抽象的“可用内存的 85%”测量?您可以设置一个 HorizontalPodAutoscaler 来创建更多 pod,而不是限制自己?
@DavidMaze 我已经用total_physical_size
和malloced_memory
更新了我的问题,过程相同,请检查。我正在尝试获取 pod 的当前内存使用情况(将在运行某些进程之前检查这一点)。不,不能创建更多的 pod,我们只有一个 pod,需要自己实现限制。
【参考方案1】:
要获得进程的总体内存消耗,请查看(并信任)操作系统的设施。
Node 的 v8.getHeapStatistics
告诉您所有 javascript 对象所在的托管(也称为垃圾收集)堆。但是在这个过程中可能还有很多其他的非垃圾收集的内存,例如节点缓冲区和某些字符串,以及不在托管堆上的各种通用基础设施。在一般的 Chrome 渲染器进程中,JavaScript 堆往往占总内存消耗的三分之一左右,但在两个方向上都有明显的异常值;对于 Node 应用程序,这在很大程度上取决于您的应用程序在做什么。
将 V8 的最大堆大小(同样,它只是进程整体内存使用的垃圾收集部分)设置为大于您可用的内存量的值没有多大意义:它会导致可避免的崩溃,因为当 V8 认为还有大量可用内存时,它不会在垃圾收集上花费太多时间,但是 OS/pod 作为一个整体可能已经面临内存不足的情况。这就是我链接另一个答案的原因:您很可能希望将最大堆大小设置为比可用内存小一点,以便为垃圾收集器提供正确的提示,告诉您何时更努力地工作以保持在限制之下。
【讨论】:
对,所以将max-old-space-size
设置为1536
会限制整体的OOM 问题吗?另外,如果我们为具有 4GB 内存的 pod 分配相同的 1536
限制,会有什么影响?此外,为了自己实现节流,使用操作系统返回的内存使用情况/sys/fs/cgroup/memory/memory.usage_in_bytes
是最好的选择。非常感谢您的详细解释。
如果你有 4GB 可用空间,那么你可能想让 JavaScript 堆使用超过 1.5GB 的空间。以上是关于如何获取运行 Node JS 应用程序的 k8s Pod 的当前和准确的内存使用情况的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Google API 服务库 (Node.js) 运行 Google 应用脚本