三叉戟拓扑抛出内存异常

时间:2015-02-13 11:45:04

标签: xml out-of-memory apache-storm apache-kafka trident

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

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

其他信息:

在处理螺栓时,我们使用DOM解析器来解析XML。我们尝试通过将XML的单个元素作为一个元组来减小单个元组的大小,但它也没有帮助。

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

2 个答案:

答案 0 :(得分: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堆空间)JVM呕吐了这个。我已经完成了大量的JVM调优等但从未见过这条消息,因为我可能已经使用旧版本的JVM进行了调优,而不是呕吐此消息。

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

对于前一种情况,您需要修复内存泄漏,并且执行此操作的方法是分析heapdump并检查消耗内存的内容,确保它不是泄漏。可以使用eclipse MAT分析heapdump,我亲自使用它。

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

  

操作:增加堆大小。可以使用命令行标志-XX:-UseGCOverheadLimit关闭超出GC Overhead限制的java.lang.OutOfMemoryError异常。

答案 1 :(得分:0)

我可以通过设置kafka获取大小和缓冲区大小来控制每次迭代中的批量大小,如下所示:

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

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