Apache NiFi - SplitText处理器出现 OutOfMemory 错误:GC overhead limit exceeded

8
我正在尝试使用HDF 1.2中的NiFi处理大型CSV文件(每个文件可能有数十亿条记录)。我已经实现了我的工作流程,并且对于小文件,一切正常。
问题在于,如果我尝试将文件大小增加到100MB(1M条记录),SplitText处理器负责将文件拆分为单个记录时会出现java.lang.OutOfMemoryError: GC overhead limit exceeded错误。我搜索了该错误,它基本上意味着垃圾收集器执行时间过长而没有获得足够的堆空间。我期望这意味着太多的流文件正在非常快地生成。
如何解决这个问题?我尝试更改nifi关于最大堆空间和其他相关内存属性的配置,但似乎没有什么作用。 目前,我添加了一个中间SplitText,行数为1K,这使我避免了错误,但我认为当传入文件的大小变得更大时,这不是一个稳定的解决方案,我担心我将从处理器中得到相同的行为。
欢迎任何建议!谢谢。
2个回答

9
错误的原因是将1M个记录按行计数分割时,您正在创建1M个流文件,这等同于1M个Java对象。使用两个SplitText处理器的方法通常可以避免同时创建所有对象。您可能可以在第一个拆分上使用更大的拆分大小,例如10k。对于十亿条记录,我想知道第三级是否有意义,从10亿拆分到大约10M,然后从10M拆分到10K,再从10K拆分到1,但我需要进行测试。
考虑的一些其他事项包括增加默认堆大小512MB(您可能已经执行),以及确定是否确实需要拆分为1行。不了解流程的其他信息很难说,但在许多情况下,如果要将每行传递到某个地方,您可能可以拥有一个处理器,该处理器读取一个大型分隔文件并将每行流式传输到目标位置。例如,PutKafka和PutSplunk就是这样工作的,它们可以接收具有1M行的文件并将每行流式传输到目标位置。

1
如果没有“一次性”完成此操作的方法,我肯定会尝试多个级别。关于PutKafka,我将在集群中设置Kafka和NiFi。忽略这将占用一些集群资源的事实,从性能或其他方面来看,是否有优势?感谢您始终提供有关NiFi行为的有用信息。 - riccamini
1
我并不是说你需要将Kafka作为其中一部分,我更多的是在询问你在将每个流文件拆分成一行后,想要在流程中做什么,以此来确定你是否真的需要这样做。很多时候人们只是想将这些行交付给外部系统,在这种情况下,可能有一个处理器可以流式传输大文件,并将每行发送到某个地方,而不会创建数百万个流文件,Kafka和Splunk只是其中的两个例子。 - Bryan Bende
我确实需要逐行拆分文件,然后对每个字段应用不同的转换/规范化。然后我将每行重新组合并在Hive上导出所有内容。 - riccamini
我在想,为什么在成功队列上设置一个10K流文件的反向压力阈值不能起到帮助作用呢?这将阻止SplitText处理器生成更多的文件,并减少JVM中对象的数量。根据你的数据流大小,你甚至可以尝试1K的阈值。 - milanchandna

0
我在使用Apache NiFi中的GetMongo处理器时遇到了类似的错误。 我将我的配置更改为:
Limit: 100
Batch Size: 10

然后错误消失了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接