Apache Storm worker 内存泄漏 - 堆外
Apache Storm worker memory leak - outside heap
我有一个 4 节点风暴集群。
Worker JVM 参数如下:
-Xms5g -Xmx15g -XX:+UseG1GC -XX:MaxDirectMemorySize=1024m
风暴版本:0.9.3
问题是:当进程内存达到 14+GB 时,Worker 往往会显着变慢。
我的Top在snapping时输出如下
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2075 root 20 0 18.132g 8.372g 12368 S 57.2 28.3 18:27.44 java
GC 日志:
3317.095: [GC pause (young), 0.1861930 secs]
[Parallel Time: 180.9 ms, GC Workers: 4]
[GC Worker Start (ms): Min: 3317095.5, Avg: 3317095.5, Max: 3317095.5, Diff: 0.0]
[Ext Root Scanning (ms): Min: 29.0, Avg: 29.4, Max: 29.7, Diff: 0.7, Sum: 117.4]
[Update RS (ms): Min: 18.0, Avg: 18.1, Max: 18.3, Diff: 0.3, Sum: 72.5]
[Processed Buffers: Min: 31, Avg: 41.2, Max: 53, Diff: 22, Sum: 165]
[Scan RS (ms): Min: 0.6, Avg: 0.7, Max: 0.8, Diff: 0.2, Sum: 2.8]
[Code Root Scanning (ms): Min: 0.1, Avg: 0.1, Max: 0.1, Diff: 0.1, Sum: 0.4]
[Object Copy (ms): Min: 132.1, Avg: 132.5, Max: 132.7, Diff: 0.6, Sum: 529.8]
[Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
[GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.0, Sum: 0.2]
[GC Worker Total (ms): Min: 180.7, Avg: 180.8, Max: 180.8, Diff: 0.1, Sum: 723.1]
[GC Worker End (ms): Min: 3317276.3, Avg: 3317276.3, Max: 3317276.3, Diff: 0.0]
[Code Root Fixup: 0.1 ms]
[Code Root Migration: 0.2 ms]
[Clear CT: 0.4 ms]
[Other: 4.6 ms]
[Choose CSet: 0.0 ms]
[Ref Proc: 1.4 ms]
[Ref Enq: 0.1 ms]
[Free CSet: 1.5 ms]
[Eden: 2366.0M(2366.0M)->0.0B(1808.0M) Survivors: 94.0M->106.0M Heap: 5052.0M(15.0G)->2698.0M(15.0G)]
[Times: user=0.73 sys=0.00, real=0.19 secs]
我可以看到只使用了 2698 MB 的堆。但是 Linux Top 显示 RES 内存为 8.372g。当 Top 内存达到 ~15GB 时,进程将开始阻塞,我想避免这种情况。
此外,我使用 XX:MaxDirectMemorySize.
缩小了直接内存被某些外部 API 阻塞的可能性
由于堆大小很大 - 如果我尝试使用分析器(在我的情况下是你的套件)拍摄内存快照,工作人员会崩溃。
我需要找到内存堵塞的根源。
此外,为了避免过多的消息,我使用 TOPOLOGY_MAX_SPOUT_PENDING 等于 5 来限制拓扑。
我正在使用 KafkaSpout - storm.kafka.KafkaSpout 来自 /net/wurstmeister/storm/storm-kafka-0.8-plus/
我还提到了这个有类似问题但使用 ZMQ 而不是 Netty 的线程,后者在较新版本的 Storm 中使用。
更新:当我移除所有螺栓并且只移除 运行 kafkaspout 时,延迟最小,也没有内存问题。所以,想必我们可以怀疑加工螺栓。
已解决。
实际上问题是 G1 的进程内存占用很大,但收集更优化。
从 ParallelOldGC 或 CMS 收集器到 G1,较大的 JVM 进程大小在很大程度上与 "accounting" 数据结构有关,例如 Remembered Sets 和 Collection Sets。
Remembered Sets 或 RSets 跟踪给定区域中的对象引用。堆中每个区域有一个 RSet。 RSet 支持区域的并行和独立收集。 RSets 的总体足迹影响小于 5%。
Collection Sets 或 CSets 将在 GC 中收集的区域集。 CSet 中的所有活动数据在 GC 期间被疏散 (copied/moved)。区域集可以是 Eden、survivor、and/or old generation。 CSets 对 JVM 大小的影响不到 1%。
我有一个 4 节点风暴集群。 Worker JVM 参数如下:
-Xms5g -Xmx15g -XX:+UseG1GC -XX:MaxDirectMemorySize=1024m
风暴版本:0.9.3
问题是:当进程内存达到 14+GB 时,Worker 往往会显着变慢。
我的Top在snapping时输出如下
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2075 root 20 0 18.132g 8.372g 12368 S 57.2 28.3 18:27.44 java
GC 日志:
3317.095: [GC pause (young), 0.1861930 secs]
[Parallel Time: 180.9 ms, GC Workers: 4]
[GC Worker Start (ms): Min: 3317095.5, Avg: 3317095.5, Max: 3317095.5, Diff: 0.0]
[Ext Root Scanning (ms): Min: 29.0, Avg: 29.4, Max: 29.7, Diff: 0.7, Sum: 117.4]
[Update RS (ms): Min: 18.0, Avg: 18.1, Max: 18.3, Diff: 0.3, Sum: 72.5]
[Processed Buffers: Min: 31, Avg: 41.2, Max: 53, Diff: 22, Sum: 165]
[Scan RS (ms): Min: 0.6, Avg: 0.7, Max: 0.8, Diff: 0.2, Sum: 2.8]
[Code Root Scanning (ms): Min: 0.1, Avg: 0.1, Max: 0.1, Diff: 0.1, Sum: 0.4]
[Object Copy (ms): Min: 132.1, Avg: 132.5, Max: 132.7, Diff: 0.6, Sum: 529.8]
[Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
[GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.0, Sum: 0.2]
[GC Worker Total (ms): Min: 180.7, Avg: 180.8, Max: 180.8, Diff: 0.1, Sum: 723.1]
[GC Worker End (ms): Min: 3317276.3, Avg: 3317276.3, Max: 3317276.3, Diff: 0.0]
[Code Root Fixup: 0.1 ms]
[Code Root Migration: 0.2 ms]
[Clear CT: 0.4 ms]
[Other: 4.6 ms]
[Choose CSet: 0.0 ms]
[Ref Proc: 1.4 ms]
[Ref Enq: 0.1 ms]
[Free CSet: 1.5 ms]
[Eden: 2366.0M(2366.0M)->0.0B(1808.0M) Survivors: 94.0M->106.0M Heap: 5052.0M(15.0G)->2698.0M(15.0G)]
[Times: user=0.73 sys=0.00, real=0.19 secs]
我可以看到只使用了 2698 MB 的堆。但是 Linux Top 显示 RES 内存为 8.372g。当 Top 内存达到 ~15GB 时,进程将开始阻塞,我想避免这种情况。
此外,我使用 XX:MaxDirectMemorySize.
缩小了直接内存被某些外部 API 阻塞的可能性由于堆大小很大 - 如果我尝试使用分析器(在我的情况下是你的套件)拍摄内存快照,工作人员会崩溃。
我需要找到内存堵塞的根源。
此外,为了避免过多的消息,我使用 TOPOLOGY_MAX_SPOUT_PENDING 等于 5 来限制拓扑。
我正在使用 KafkaSpout - storm.kafka.KafkaSpout 来自 /net/wurstmeister/storm/storm-kafka-0.8-plus/
我还提到了这个有类似问题但使用 ZMQ 而不是 Netty 的线程,后者在较新版本的 Storm 中使用。
更新:当我移除所有螺栓并且只移除 运行 kafkaspout 时,延迟最小,也没有内存问题。所以,想必我们可以怀疑加工螺栓。
已解决。 实际上问题是 G1 的进程内存占用很大,但收集更优化。
从 ParallelOldGC 或 CMS 收集器到 G1,较大的 JVM 进程大小在很大程度上与 "accounting" 数据结构有关,例如 Remembered Sets 和 Collection Sets。
Remembered Sets 或 RSets 跟踪给定区域中的对象引用。堆中每个区域有一个 RSet。 RSet 支持区域的并行和独立收集。 RSets 的总体足迹影响小于 5%。
Collection Sets 或 CSets 将在 GC 中收集的区域集。 CSet 中的所有活动数据在 GC 期间被疏散 (copied/moved)。区域集可以是 Eden、survivor、and/or old generation。 CSets 对 JVM 大小的影响不到 1%。