docker - 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 内存增长的原因?
解决方案
您需要在非 docker 环境中复制它,因为使用 docker,内存会增加。
正如我在“在 Docker 容器中运行的 JVM 的驻留集大小 (RSS) 和 Java 总提交内存 (NMT) 之间的差异”中解释的那样,docker有一些错误(如issue 10824和issue 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 监视器(我将对其进行相同的修改以排除缓存)。
推荐阅读
- android - iBeaconResult 不返回信标对象数组
- html - 我的图片和段落位置不正确
- python - hr.employee 上 odoo 上的员工人数
- google-analytics - 跨域跟踪:跟踪用户是否真正跨域
- cucumber - 空手道 + Cucumber 报告缺少被调用场景响应的文档字符串
- google-apps-script - 如何选择段落中所有带下划线的文本
- c# - 从 RazorProjectEngine 设置生成的 C# 代码的类名
- angular - 角度材料:弹出窗口:允许窗口移动到第二个监视器屏幕
- python - 如何限制pyglet中的FPS?(窗口 on_draw 事件)
- postgresql - 将智能表同步到 postgres 表?