0

我正在从 Storm 的传统拓扑转移到 Trident 拓扑,它在将元组推送到数据库之前维护成批的元组。我们将 XML 处理为单个元组。在一次处理一个 xml 的传统拓扑中,这很好用。但是在 Trident 拓扑中,在提交到数据库之前,它会在内存中保留大量元组,这会导致内存不足异常。也不清楚风暴如何决定批量大小以及它在每次迭代中的变化。以下是我们收到的错误:

java.lang.OutOfMemoryError: GC 开销限制在 java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130) 在 java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder) 的 java.util.Arrays.copyOf(Arrays.java:2367) .java:114) 在 java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:415) 在 java.lang.StringBuilder.append(StringBuilder.java:132) 在 clojure.core$str$fn__3896.invoke(core.clj: 517) 在 clojure.core$str.doInvoke(core.clj:519) 在 clojure.lang.RestFn.invoke(RestFn.java:423) 在 backtype.storm.daemon.executor$mk_task_receiver$fn__5564.invoke(executor.clj :397) 在 backtype.storm.disruptor$clojure_handler$reify__745.onEvent(disruptor.clj:58) 在 backtype.storm.utils.DisruptorQueue.consumeBatchToCursor(DisruptorQueue.java:125) 在 backtype.storm.utils.DisruptorQueue。consumeBatchWhenAvailable(DisruptorQueue.java:99) at backtype.storm.disruptor$consume_batch_when_available.invoke(disruptor.clj:80) at backtype.storm.daemon.executor$fn__5641$fn__5653$fn__5700.invoke(executor.clj:746) at backtype .storm.util$async_loop$fn__457.invoke(util.clj:431) 在 clojure.lang.AFn.run(AFn.java:24) 在 java.lang.Thread.run(Thread.java:745)

更多信息:

在处理螺栓时,我们使用 DOM 解析器来解析 XML。我们试图通过将 XML 的单个元素作为一个元组来减小单个元组的大小,但这也无济于事。

可能的解决方案可能包括限制存储在内存中的批次大小或使用快速垃圾收集。

4

2 回答 2

0

我可以通过设置 kafka fetch size 和 buffer size 来控制每次迭代中的批量大小,如下所示:

    spoutConf.fetchSizeBytes = 5*1024*1024;
    spoutConf.bufferSizeBytes = 5*1024*1024;

这限制了保存在内存中的数据量。我们将不得不根据您的用例调整此限制,以便内存中的数据对于您的系统来说不会太大,但系统可以提供最大的吞吐量。

于 2015-02-20T10:20:40.953 回答
0

java.lang.OutOfMemoryError:超过 GC 开销限制

以下是异常的原因

详细消息“超出 GC 开销限制”表示垃圾收集器一直在运行,Java 程序进展缓慢。垃圾回收后,如果 Java 进程花费超过大约 98% 的时间进行垃圾回收,并且如果它回收的堆少于 2%,并且到目前为止一直在做最后 5 个(编译时间常数)连续垃圾集合,然后抛出 java.lang.OutOfMemoryError。通常会抛出此异常,因为实时数据量几乎无法放入 Java 堆中,几乎没有用于新分配的可用空间。

详细信息可以在这里找到

http://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/memleaks.html

此问题的真正原因是应用程序的内存使用量增加,并且 GC 无法清除应用程序继续工作可能需要的足够内存,因此在抛出 OOME(java.lang.OutOfMemoryError: Java heap space ) JVM 吐了这个。我已经做了很多 JVM 的调优等工作,但从未见过这条消息,因为我可能已经对旧版本的 JVM 进行了调优,但它并没有吐出这条消息。

从逻辑上讲,有两种可能看到此消息 - 应用程序正在泄漏内存。- 应用程序正在消耗更多内存。

对于前一种情况,您需要修复内存泄漏,解决方法是分析堆转储并检查正在消耗内存的内容,确保它不是泄漏。heapdump可以用eclipse MAT分析,我个人用过。

对于后一种情况,您将不得不增加堆大小,这也在我上面粘贴的链接中进行了说明,您需要执行以下操作

行动:增加堆大小。超过 GC Overhead limit 的 java.lang.OutOfMemoryError 异常可以使用命令行标志 -XX:-UseGCOverheadLimit 关闭。

于 2015-02-18T08:55:34.487 回答