2016-08-11 2 views
0

私はjava.util.logging.Loggerを使用する既存のJavaパッケージを実行するために、スパークを使用しています、と私はエラーを取得しています:スパークjava.util.logging.Loggerの

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: [email protected]) 
    - field (class: edu.uth.clamp.nlp.ner.CRFNameEntityRecognizer, name: logger, type: class java.util.logging.Logger) 
    - object (class edu.uth.clamp.nlp.ner.CRFNameEntityRecognizer, [email protected]) 
    - 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, [email protected]) 
    - writeObject data (class: java.util.ArrayList) 

答えて

0

あなたのコードは、おそらく

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を使用してください。

0

rdd/dstreamの変換の中で渡される関数は、直列化可能である必要があります。 java.util.logging.Loggerはシリアライズ可能ではないので、関数内にロギング関連のコードを持つべきではありません。ログを単純なprintlnに置き換えることができます。または、ここで提案されているオプションを試すこともできます。

Apache Spark logging within Scala

ログがドライバコードで存在することが可能です。 そして、関数の外部にある、シリアライズ可能でない変数を参照していないことを確認してください。クロージャによるシリアライゼーションの理解を深めるには、クロージャdocdoc2の概念を学んでください。

2

ロガーインスタンスをシリアル化しようとしていることを確認してください。ロガーフィールドを静的または一時的なものにしてください。

1

ログオブジェクトの作成中に@transient lazy valを使用してみてください。また、それはスパーク自体がこの世話をするようにクロージャの中でそれを使用する方が良いです。

0

ロガーはシリアライズ可能ではなく、エグゼキュータからアクセスしようとしている可能性があります。私はそれが怠け者として定義することを提案します

lazy val logger = .... 

しかし、欠点は、ドライバ内でロガーを使用すべきではないということです。非常にセクシーではない別のオプションは、エグゼキュータのために別のロガーを持っているということです。