RDDはSerialisableインターフェースを拡張するため、これがタスクの失敗の原因ではありません。これはRDD
、Sparkでシリアル化して回避できることを意味しませんNotSerializableException
Sparkは分散コンピューティングエンジンであり、その主な抽象概念は、分散コレクションと見なすことができる復元力のある分散データセット(RDD)です。基本的に、RDDの要素はクラスターのノード間で分割されますが、Sparkはユーザーからこれを抽象化し、ユーザーがローカルのRDD(コレクション)と同様にRDD(コレクション)を操作できるようにします。
あまりにも多くの詳細に入るが、あなたはRDD(上の異なる変換を実行するとしないmap
、flatMap
、filter
など)、あなたの変換コード(クロージャ)は次のとおりです。
- ドライバノードでシリアル化され、
- クラスタ内の適切なノードに出荷され、
- 逆シリアル化、
- そして最後にノードで実行されます
もちろん、これをローカルで(例のように)実行することもできますが、それらすべてのフェーズ(ネットワーク経由の配送を除く)は引き続き発生します。[これにより、本番環境にデプロイする前でもバグをキャッチできます]
2番目のケースで何が起こるかはtesting
、map関数内からクラスで定義されたメソッドを呼び出すことです。Sparkはそれを認識し、メソッドを単独でシリアル化することはできないため、Sparkはクラス全体 をシリアル化しようとしtesting
ます。そのため、コードは別のJVMで実行されても機能します。次の2つの可能性があります。
クラステストをシリアライズ可能にすると、クラス全体をSparkでシリアライズできます。
import org.apache.spark.{SparkContext,SparkConf}
object Spark {
val ctx = new SparkContext(new SparkConf().setAppName("test").setMaster("local[*]"))
}
object NOTworking extends App {
new Test().doIT
}
class Test extends java.io.Serializable {
val rddList = Spark.ctx.parallelize(List(1,2,3))
def doIT() = {
val after = rddList.map(someFunc)
after.collect().foreach(println)
}
def someFunc(a: Int) = a + 1
}
またはsomeFunc
、メソッドの代わりに関数を作成し(関数はScalaのオブジェクトです)、Sparkがそれをシリアル化できるようにします。
import org.apache.spark.{SparkContext,SparkConf}
object Spark {
val ctx = new SparkContext(new SparkConf().setAppName("test").setMaster("local[*]"))
}
object NOTworking extends App {
new Test().doIT
}
class Test {
val rddList = Spark.ctx.parallelize(List(1,2,3))
def doIT() = {
val after = rddList.map(someFunc)
after.collect().foreach(println)
}
val someFunc = (a: Int) => a + 1
}
クラスのシリアライゼーションに関する同様の、しかし同じではない問題はあなたにとって興味深いものであり、このSpark Summit 2013プレゼンテーションでそれを読むことができます。
注意点として、あなたが書き換え可能rddList.map(someFunc(_))
にrddList.map(someFunc)
、彼らはまったく同じです。通常、2番目の方が読みやすく、冗長ではないため、2番目の方法が推奨されます。
編集(2015-03-15):SPARK-5307にSerializationDebuggerが導入され、Spark 1.3.0がそれを使用する最初のバージョンです。NotSerializableExceptionにシリアル化パスを追加します。NotSerializableExceptionが発生すると、デバッガーはオブジェクトグラフにアクセスして、シリアル化できないオブジェクトへのパスを見つけ、ユーザーがオブジェクトを見つけるのに役立つ情報を作成します。
OPの場合、これはstdoutに出力されます。
Serialization stack:
- object not serializable (class: testing, value: testing@2dfe2f00)
- field (class: testing$$anonfun$1, name: $outer, type: class testing)
- object (class testing$$anonfun$1, <function1>)