当我使用数据流时,我需要创建一些字符串行,其中用户ID列表用逗号分隔。然后在GCS中写入结果。
不幸的是,在DoFn的processElement期间,每行都有太多用户导致java.lang.OutOfMemoryError。
有没有办法避免OutOfMemory异常并成功写入fat带有文本文件的GCS中每一行的行?
我的源代码如下所示。
PCollection<KV<String, String>> rows = someData
.apply(Combine.<String, String>perKey(new CombineUserIds()));
public static class CombineUserIds implements SerializableFunction<Iterable<String>, String> {
private static final long serialVersionUID = 0;
@Override
public String apply(Iterable<String> userIdList) {
return Joiner.on(",").join(userIdList);
}
}
此处,源代码中的someData
为PCollection<KV<String, String>>
类型,其键为group_id,值为user_id。
以下是完整的错误消息
(b997767fac436e5c): java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3332) at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:137) at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:121) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:421) at java.lang.StringBuilder.append(StringBuilder.java:136) at java.lang.StringBuilder.append(StringBuilder.java:76) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:457) at java.lang.StringBuilder.append(StringBuilder.java:166) at java.lang.StringBuilder.append(StringBuilder.java:76) at com.google.common.base.Joiner.appendTo(Joiner.java:111) at com.google.common.base.Joiner.appendTo(Joiner.java:152) at com.google.common.base.Joiner.join(Joiner.java:193) at com.google.common.base.Joiner.join(Joiner.java:183) at com.moloco.dataflow.ml.adhoc.GenerateMLUserProfileSet$CombineUserIds.apply(GenerateMLUserProfileSet.java:189) at com.moloco.dataflow.ml.adhoc.GenerateMLUserProfileSet$CombineUserIds.apply(GenerateMLUserProfileSet.java:184) at com.google.cloud.dataflow.sdk.transforms.Combine$IterableCombineFn.mergeToSingleton(Combine.java:1613) at com.google.cloud.dataflow.sdk.transforms.Combine$IterableCombineFn.mergeAccumulators(Combine.java:1591) at com.google.cloud.dataflow.sdk.transforms.Combine$IterableCombineFn.mergeAccumulators(Combine.java:1536) at com.google.cloud.dataflow.sdk.transforms.Combine$CombineFn$2.mergeAccumulators(Combine.java:489) at com.google.cloud.dataflow.sdk.runners.worker.GroupAlsoByWindowsParDoFnFactory$MergingKeyedCombineFn.extractOutput(GroupAlsoByWindowsParDoFnFactory.java:249) at com.google.cloud.dataflow.sdk.runners.worker.GroupAlsoByWindowsParDoFnFactory$MergingKeyedCombineFn.extractOutput(GroupAlsoByWindowsParDoFnFactory.java:216) at com.google.cloud.dataflow.sdk.util.GroupAlsoByWindowsAndCombineDoFn$KeyedCombineFnRunner.extractOutput(GroupAlsoByWindowsAndCombineDoFn.java:243) at com.google.cloud.dataflow.sdk.util.GroupAlsoByWindowsAndCombineDoFn.closeWindow(GroupAlsoByWindowsAndCombineDoFn.java:206) at com.google.cloud.dataflow.sdk.util.GroupAlsoByWindowsAndCombineDoFn.processElement(GroupAlsoByWindowsAndCombineDoFn.java:192) at com.google.cloud.dataflow.sdk.util.SimpleDoFnRunner.invokeProcessElement(SimpleDoFnRunner.java:49) at com.google.cloud.dataflow.sdk.util.DoFnRunnerBase.processElement(DoFnRunnerBase.java:138) at com.google.cloud.dataflow.sdk.runners.worker.SimpleParDoFn.processElement(SimpleParDoFn.java:190) at com.google.cloud.dataflow.sdk.runners.worker.ForwardingParDoFn.processElement(ForwardingParDoFn.java:42) at com.google.cloud.dataflow.sdk.runners.worker.DataflowWorkerLoggingParDoFn.processElement(DataflowWorkerLoggingParDoFn.java:47) at com.google.cloud.dataflow.sdk.util.common.worker.ParDoOperation.process(ParDoOperation.java:53) at com.google.cloud.dataflow.sdk.util.common.worker.OutputReceiver.process(OutputReceiver.java:52) at com.google.cloud.dataflow.sdk.util.common.worker.ReadOperation.runReadLoop(ReadOperation.java:226)
答案 0 :(得分:-2)
来自Oracle docs,
线程中的异常thread_name:java.lang.OutOfMemoryError:Java堆空间
原因:详细消息Java堆空间表示对象无法 在Java堆中分配。这个错误并不一定意味着 内存泄漏。问题可以像配置问题一样简单, 指定堆大小的位置(如果不是,则为默认大小) 指定的)不足以应用。
解决方案1:增加JVM堆大小,如下所示。
您可以为每个项目指定项目需要多少堆空间
以下是Eclipse:
右键单击
Run As - Run Configuration - Arguments - Vm Arguments,
然后添加此
-Xmx1024
或
-Xmx2048m
解决方案2(仅在尝试过解决方案1之后):
再次来自Oracle docs,
3.4.3监控即将结束的对象 使用“Java堆空间”&gt;抛出OutOfMemoryError异常时详情 消息,原因可能是过度使用终结器。要诊断 这个,你有几个选项来监控对象的数量 待定稿:
JConsole管理工具可用于监控的数量 待完成的对象。此工具报告待处理 “摘要”选项卡窗格中的内存统计信息中的最终计数。 计数是近似值,但可用于表征 应用并理解它是否依赖于最终确定。
在Oracle Solaris和Linux操作系统上,jmap实用程序可以是 与-finalizerinfo选项一起使用以打印有关对象的信息 等待最终确定。
应用程序可以报告待处理的对象的大致数量 使用getObjectPendingFinalizationCount方法完成终结 java.lang.management.MemoryMXBean类。 API的链接 文档和示例代码可以在Custom Diagnostic Tools中找到。示例代码可以很容易地扩展到包含 报告待定的最终计数。