【问题标题】:spark java.util.logging.Logger火花 java.util.logging.Logger
【发布时间】:2016-12-18 17:46:42
【问题描述】:

我正在使用 Spark 运行使用 java.util.logging.Logger 的现有 Java 包,但出现错误:

org.apache.spark.SparkException: Task not serializable
    at org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:304)
    at org.apache.spark.util.ClosureCleaner$.org$apache$spark$util$ClosureCleaner$$clean(ClosureCleaner.scala:294)
    at org.apache.spark.util.ClosureCleaner$.clean(ClosureCleaner.scala:122)
    at org.apache.spark.SparkContext.clean(SparkContext.scala:2055)
    at org.apache.spark.rdd.RDD$$anonfun$foreach$1.apply(RDD.scala:911)
    at org.apache.spark.rdd.RDD$$anonfun$foreach$1.apply(RDD.scala:910)
    at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:150)
    at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:111)
    at org.apache.spark.rdd.RDD.withScope(RDD.scala:316)
    at org.apache.spark.rdd.RDD.foreach(RDD.scala:910)
    at org.apache.spark.api.java.JavaRDDLike$class.foreach(JavaRDDLike.scala:332)
    at org.apache.spark.api.java.AbstractJavaRDDLike.foreach(JavaRDDLike.scala:46)
    at edu.uth.clamp.nlp.main.RunPipelineWithSpark.processFolder(RunPipelineWithSpark.java:271)
    at edu.uth.clamp.nlp.main.RunPipelineWithSpark.process(RunPipelineWithSpark.java:179)
    at edu.uth.clamp.nlp.main.RunPipelineWithSpark.main(RunPipelineWithSpark.java:136)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:731)
    at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:181)
    at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:206)
    at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:121)
    at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.io.NotSerializableException: java.util.logging.Logger
Serialization stack:
    - object not serializable (class: java.util.logging.Logger, value: java.util.logging.Logger@a23dc07)
    - field (class: edu.uth.clamp.nlp.ner.CRFNameEntityRecognizer, name: logger, type: class java.util.logging.Logger)
    - object (class edu.uth.clamp.nlp.ner.CRFNameEntityRecognizer, edu.uth.clamp.nlp.ner.CRFNameEntityRecognizer@5199fdf9)
    - field (class: edu.uth.clamp.nlp.uima.NameEntityUIMA, name: recognizer, type: class edu.uth.clamp.nlp.ner.CRFNameEntityRecognizer)
    - object (class edu.uth.clamp.nlp.uima.NameEntityUIMA, edu.uth.clamp.nlp.uima.NameEntityUIMA@23a84ec4)
    - writeObject data (class: java.util.ArrayList)

【问题讨论】:

    标签: logging apache-spark


    【解决方案1】:

    Logger 不可序列化,很可能您正试图从执行程序访问它。我建议将其定义为懒惰

    lazy val logger = ....
    

    但是缺点是您不应该在驱动程序中使用记录器。另一个不是很性感的选择是为执行者设置另一个记录器..

    【讨论】:

      【解决方案2】:

      在创建日志对象时尝试使用@transient lazy val。此外,最好在闭包内使用它,这样 spark 自己会处理这个问题。

      【讨论】:

        【解决方案3】:

        请检查您是否尝试序列化记录器实例,将记录器字段设置为静态或瞬态。

        【讨论】:

          【解决方案4】:

          Spark 期望在 rdd/dstream 的转换中传递的函数应该是可序列化的。由于 java.util.logging.Logger 不是可序列化的,因此函数内不应包含与日志记录相关的代码。您可以用简单的 println 替换日志。或者您可以尝试此处建议的选项。

          Apache Spark logging within Scala

          请注意,日志可以存在于驱动程序代码中。 并确保它没有引用函数之外不可序列化的任何变量。为了更好地理解闭包导致的序列化,学习闭包的概念doc doc2

          【讨论】:

            【解决方案5】:

            您的代码可能类似于

            NameEntityUIMA nameEntity = ...;
            JavaRDD<SomeType> rdd = ...;
            rdd.foreach(x -> /* code using nameEntity */);
            

            foreach 必须序列化其参数以将其发送到每个节点;因为参数使用了nameEntity,所以也需要序列化,但是不能序列化(并且由于Java序列化的设计,这只是在运行时检测到,而不是给出编译错误)。相反,您想在每个分区上创建 nameEntity。你可以这样做

            JavaRDD<SomeType> rdd = ...;
            rdd.foreach(x -> {
                NameEntityUIMA nameEntity = ...;
                /* code using nameEntity */
            });
            

            但是这会为 RDD 的每个元素创建一个新的nameEntity,这会非常糟糕。请改用foreachPartition

            【讨论】:

              猜你喜欢
              • 2011-01-22
              • 1970-01-01
              • 2017-04-27
              • 1970-01-01
              • 2016-10-20
              • 2023-03-26
              • 2016-06-07
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多