首页 > 解决方案 > Nifi 1.6.0 内存泄漏

问题描述

我们在生产中运行 NiFi 1.6.0 的 Docker 容器,并且不得不遇到内存泄漏。

启动后,应用程序运行良好,但是在 4-5 天后,主机上的内存消耗不断增加。在 NiFi 集群 UI 中检查时,JVM 堆大小几乎没有使用 30% 左右,但操作系统级别的内存达到 80-90%。

在运行 docker starts 命令时,我们发现 NiFi docker 容器正在消耗内存。

收集 JMX 指标后,我们发现 RSS 内存不断增长。这可能是什么潜在原因?在集群对话框的 JVM 选项卡中,年轻 GC 似乎也在及时发生,旧 GC 计数显示为 0。

我们如何确定导致 RSS 内存增长的原因?

标签: dockermemory-leaksapache-nifi

解决方案


您需要在非 docker 环境中复制它,因为使用 docker,内存会增加
正如我在“在 Docker 容器中运行的 JVM 的驻留集大小 (RSS) 和 Java 总提交内存 (NMT) 之间的差异”中解释的那样,docker有一些错误(如issue 10824issue 15020),这些错误会阻止准确报告内存由 Docker 容器中的 Java 进程使用。

这就是为什么一个插件signalfx/docker-collectd-plugin(两周前)在其PR - Pull Request - 35中提到“从内存使用百分比指标中扣除缓存数字”:

目前,返回给 SignalFX 的容器/cgroup 的内存使用计算包括 Linux 页面缓存。
这通常被认为是不正确的,并且可能导致人们在他们的应用程序中追逐幻像内存泄漏。

为了演示当前计算为什么不正确,您可以运行以下命令来查看 I/O 使用情况如何影响 cgroup 中的整体内存使用情况:

docker run --rm -ti alpine
cat /sys/fs/cgroup/memory/memory.stat
cat /sys/fs/cgroup/memory/memory.usage_in_bytes
dd if=/dev/zero of=/tmp/myfile bs=1M count=100
cat /sys/fs/cgroup/memory/memory.stat
cat /sys/fs/cgroup/memory/memory.usage_in_bytes

您应该看到,usage_in_bytes仅创建一个 100MB 的文件,该值就增加了 100MB。该文件尚未被应用程序加载到匿名内存中,但由于它现在位于页面缓存中,因此容器内存使用率似乎更高。
从usage_in_bytes 中减去memory.stat 中的缓存数字表明匿名内存的真正使用并没有上升。

现在,signalFX 指标与运行 docker stats 时看到的不同,后者使用了我在这里的计算。
似乎知道容器的页面缓存使用可能很有用(尽管我很难想到什么时候),但是知道它作为 cgroup 总体使用百分比的一部分是没有用的,因为它会伪装你的实际 RSS内存使用。
在最大堆大小与 cgroup 内存限制一样大或大于 cgroup 内存限制的垃圾收集应用程序中(例如,java 的 -Xmx 参数,或服务器模式下的 .NET 核心),百分比趋向于接近 100 % 然后只是悬停在那里,假设运行时可以正确看到 cgroup 内存限制。
如果您使用的是智能代理,我建议您使用docker-container-stats 监视器(我将对其进行相同的修改以排除缓存)。


推荐阅读