【发布时间】:2018-04-11 17:56:21
【问题描述】:
我有一个包含隐式转换的实用程序对象:
object Util {
implicit class SparkView(sc: SparkContext) {
def do(): Unit = sc.parallelize(1 to 10).foreach {
doSomething()
}
}
def doSomething(): Unit
}
开箱即用:
val sc = new SparkContext()
sc.do()
但是,当我将上述 Util 实现更改为稍有不同时:
class Util {
implicit class SparkView(sc: SparkContext) {
def do(): Unit = sc.parallelize(1 to 10).foreach {
doSomething()
}
}
def doSomething(): Unit
}
case object Util extends Util
它的相同用法给出以下错误:
> Task not serializable org.apache.spark.SparkException: Task not
> serializable at
> org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:340)
> at
> org.apache.spark.util.ClosureCleaner$.org$apache$spark$util$ClosureCleaner$$clean(ClosureCleaner.scala:330)
> at
> org.apache.spark.util.ClosureCleaner$.clean(ClosureCleaner.scala:156)
> ...
> Caused by: java.io.NotSerializableException:
> my.package.Util$SparkView
> Serialization stack:
> - object not serializable (class: my.package.Util$SparkView, value:
> my.package.Util$SparkView@4f03729f)
事实证明,在第二种情况下,函数 doSomething() 被序列化并附带了无用的东西(实际的函数签名变为this.$outer.doSomething())。一个直接的解决方法是将 SparkView 的所有实例声明为瞬态,这样它就不会被序列化和交付,并且可以从单例 Util 中从头开始读取函数 doSomething。我应该如何轻松实现?
【问题讨论】:
标签: scala apache-spark serialization