【问题标题】:How to fix Dataflow unable to serialize my DoFn?如何修复 Dataflow 无法序列化我的 DoFn?
【发布时间】:2015-03-17 21:32:09
【问题描述】:

当我运行我的 Dataflow 管道时,我收到以下异常,抱怨我的 DoFn 无法序列化。我该如何解决这个问题?

这是堆栈跟踪:

Caused by: java.lang.IllegalArgumentException: unable to serialize contrail.dataflow.AvroMRTransforms$AvroReducerDoFn@bba0fc2
    at com.google.cloud.dataflow.sdk.util.SerializableUtils.serializeToByteArray(SerializableUtils.java:51)
    at com.google.cloud.dataflow.sdk.util.SerializableUtils.ensureSerializable(SerializableUtils.java:81)
    at com.google.cloud.dataflow.sdk.runners.DirectPipelineRunner$Evaluator.ensureSerializable(DirectPipelineRunner.java:784)
    at com.google.cloud.dataflow.sdk.transforms.ParDo.evaluateHelper(ParDo.java:1025)
    at com.google.cloud.dataflow.sdk.transforms.ParDo.evaluateSingleHelper(ParDo.java:963)
    at com.google.cloud.dataflow.sdk.transforms.ParDo.access$000(ParDo.java:441)
    at com.google.cloud.dataflow.sdk.transforms.ParDo$1.evaluate(ParDo.java:951)
    at com.google.cloud.dataflow.sdk.transforms.ParDo$1.evaluate(ParDo.java:946)
    at com.google.cloud.dataflow.sdk.runners.DirectPipelineRunner$Evaluator.visitTransform(DirectPipelineRunner.java:611)
    at com.google.cloud.dataflow.sdk.runners.TransformTreeNode.visit(TransformTreeNode.java:200)
    at com.google.cloud.dataflow.sdk.runners.TransformTreeNode.visit(TransformTreeNode.java:196)
    at com.google.cloud.dataflow.sdk.runners.TransformHierarchy.visit(TransformHierarchy.java:109)
    at com.google.cloud.dataflow.sdk.Pipeline.traverseTopologically(Pipeline.java:204)
    at com.google.cloud.dataflow.sdk.runners.DirectPipelineRunner$Evaluator.run(DirectPipelineRunner.java:584)
    at com.google.cloud.dataflow.sdk.runners.DirectPipelineRunner.run(DirectPipelineRunner.java:328)
    at com.google.cloud.dataflow.sdk.runners.DirectPipelineRunner.run(DirectPipelineRunner.java:70)
    at com.google.cloud.dataflow.sdk.Pipeline.run(Pipeline.java:145)
    at contrail.stages.DataflowStage.stageMain(DataflowStage.java:51)
    at contrail.stages.NonMRStage.execute(NonMRStage.java:130)
    at contrail.stages.NonMRStage.run(NonMRStage.java:157)
    at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:65)
    at contrail.stages.ValidateGraphDataflow.main(ValidateGraphDataflow.java:139)
    ... 6 more
Caused by: java.io.NotSerializableException: org.apache.hadoop.mapred.JobConf
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
    at com.google.cloud.dataflow.sdk.util.SerializableUtils.serializeToByteArray(SerializableUtils.java:47)
    ... 27 more

【问题讨论】:

    标签: google-cloud-dataflow


    【解决方案1】:

    如果您滚动查看堆栈跟踪,其中一个原因会清楚地识别出不可序列化的数据。

    Caused by: java.io.NotSerializableException: org.apache.hadoop.mapred.JobConf
    

    问题是我的 DoFn 在构造函数中获取 JobConf 实例并将其存储在实例变量中。我假设 JobConf 是可序列化的,但事实证明不是。

    为了解决这个问题,我做了以下操作

    • 我将 JobConf 成员变量标记为瞬态,这样它就不会被序列化。
    • 我创建了一个单独的 byte[] 类型变量来存储 JobConf 的序列化版本
    • 在我的构造函数中,我将 JobConf 序列化为一个 byte[] 并将其存储在一个实例变量中。
    • 我覆盖 startBundle 并从 byte[] 反序列化 JobConf

    这是我的 DoFn 的 gist

    【讨论】:

    • 此解决方案与我找到的解决方案非常接近。我的问题是通过 DoFn 函数序列化 Schema (avro)。我找到的方法是将 Schema 字符串传递给 Function 类的构造函数,然后在 processElement() 方法中进行解析。这种方法对要转换的 PCollection 的每个条目进行模式反序列化,从而降低性能,我想知道您的解决方案的行为是否相同,或者它只是在您在 startBound() 方法中看到它时进行反序列化/解析。 From java doc 在执行时未指定。谢谢
    • 你是如何实现serializeJobConf()方法的?
    【解决方案2】:

    补充 Jeremy 所说的话...

    Serializable 问题的另一个常见原因是当您在非静态上下文中使用匿名 DoFn 时。匿名内部类有一个指向封闭类的隐式指针,这将导致它也被序列化。

    【讨论】:

    • 好的...这没有任何意义,但实际上当我将 DoFn 从匿名更改为真实类时,问题就消失了。就我而言,我使用 Kotlin 而不是 java。
    猜你喜欢
    • 1970-01-01
    • 2011-09-21
    • 2019-12-06
    • 1970-01-01
    • 2017-02-27
    • 2019-06-24
    • 1970-01-01
    • 2019-03-07
    • 2019-10-28
    相关资源
    最近更新 更多