![](/img/trans.png)
[英]SparkException: Task not serializable on class: org.apache.avro.generic.GenericDatumReader
[英]Generic parser class `Task not serializable`
我正在嘗試構造一個類,該類接收解析器作為參數,並在每一行上使用該解析器。 下面是一個最小的示例,您可以將其粘貼到spark-shell
。
import scala.util.{Success,Failure,Try}
import scala.reflect.ClassTag
class Reader[T : ClassTag](makeParser: () => (String => Try[T])) {
def read(): Seq[T] = {
val rdd = sc.parallelize(Seq("1","2","oops","4")) mapPartitions { lines =>
// Since making a parser can be expensive, we want to make only one per partition.
val parser: String => Try[T] = makeParser()
lines flatMap { line =>
parser(line) match {
case Success(record) => Some(record)
case Failure(_) => None
}
}
}
rdd.collect()
}
}
class IntParser extends (String => Try[Int]) with Serializable {
// There could be an expensive setup operation here...
def apply(s: String): Try[Int] = Try { s.toInt }
}
但是,當我嘗試運行類似new Reader(() => new IntParser).read()
(類型檢查就很好)時,我得到了可怕的org.apache.spark.SparkException: Task not serializable
與閉包有關的org.apache.spark.SparkException: Task not serializable
錯誤。
為什么會有錯誤,並且有辦法重新設計以上內容以避免發生這種情況(同時使Reader
保持通用)?
問題是makeParser
對於class Reader
是變量,並且由於您在rdd轉換中使用它,因此spark將嘗試序列化整個不可序列化的Reader類。 因此,您將獲得任務不可序列化的異常。
將Serializable添加到類Reader中將與您的代碼一起使用。 但這不是一個好習慣,因為它將序列化可能不需要的整個類變量。
通常,您可以使用函數而不是方法來避免序列化問題。 因為在scala中,函數實際上是對象,因此將被序列化。
請參閱此答案: 任務不可序列化:僅在類而非對象上調用閉包之外的函數時,java.io.NotSerializableException
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.