只有一个NotSerializableException
我无法理解。使用Spark 1.5.0启动EMR集群,然后输入shell spark-shell --master local
(如果您选择yarn-client
而不是local
,则没有区别。)
然后运行以下代码:
class MaybeSerializable() {
def add(i: Int) = i + 1
}
val foo = new MaybeSerializable()
sc.makeRDD(1 to 1000).map(foo.add).reduce(_ + _)
我保证会导致org.apache.spark.SparkException: Task not serializable
现在使用相同版本的Spark "org.apache.spark" %% "spark-core" % "1.5.0"
创建一个sbt项目,然后输入sbt console
,然后运行
import org.apache.spark.SparkContext
val sc = new SparkContext("local", "shell")
class MaybeSerializable() {
def add(i: Int) = i + 1
}
val foo = new MaybeSerializable()
sc.makeRDD(1 to 1000).map(foo.add).reduce(_ + _)
我向你保证它会奏效!没有例外!
如果有人能够解释这一点,我会很高兴。
答案 0 :(得分:0)
关于行为的不一致,我不是Spark专家,但我会说在第一种情况下,当使用Yarn EMR时,整个“MaybeSerializable”类肯定会被序列化并被发送给执行者由司机。由于它不可序列化,因此会出现“NotSerializableException”异常。
另一方面,在第二种情况下,我不太确定该类是否被序列化,这就是为什么你没有得到异常。底层架构正在推动序列化的需要与否。当你使用sbt时,如果驱动程序没有将类的序列化版本发送到任何进程,我不会感到惊讶。在这种情况下,由于不需要,类是否可序列化并不重要。
我可以用独立的方式在我的计算机中重现第一个问题,并且我摆脱它使这个类可序列化:“类MaybeSerializable()扩展Serializable”。这是我使用(和/或匿名函数)的最佳实践,以确保我的代码将以任何集群类型运行,并且序列化行为将在集群中保持一致。
我希望它有所帮助。