当processElement的输出为fat时,处理内存不足异常

时间:2016-07-23 03:45:51

标签: java google-cloud-dataflow


当我使用数据流时,我需要创建一些字符串行,其中用户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);
  }
}

此处,源代码中的someDataPCollection<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)

1 个答案:

答案 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中找到。示例代码可以很容易地扩展到包含   报告待定的最终计数。