java.io.NotSerializableException:org.apache.spark.SparkContext序列化堆栈: - 对象不可序列化

时间:2015-08-18 06:13:41

标签: java apache-spark serialization

错误可以在spark-shell中重现。 基本上,我使用生成RDD的方法定义一个类,然后在RDD上执行映射操作,生成序列化错误。

如果我没有方法并且只有执行方法步骤的语句,那么一切正常。

这里的代码可以在spark-shell中运行我定义了一个类然后我实例化了这个类。

首先是进口

import java.nio.file.{Files}
import java.io._
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import scala.io.Source
import scala.collection.mutable.ArrayBuffer

这是一个带有方法和带有匿名函数的映射的类,用于计算字符串中的分隔符

class DataValidation(datasetPath: String, datasetName: String, separator:    
String, encoding: String, sc: SparkContext) extends Serializable {

// open file and load distribute... and try playing around with it...
// RDD data declaration, reading dataset on RDD without header

var dataset = datasetPath + "//" + datasetName + ".csv"

def textfile_encoding(datasetIn: String, encodingIn: String) : RDD[String] = {
var characters = ArrayBuffer[String]()
    for (line <- Source.fromFile(dataset, encoding).getLines()) {
         characters += line
    }
sc.parallelize(characters)

}
val rdd = this.textfile_encoding(dataset,encoding)
val separatorCount = rdd.map(_.count(_ == separator.charAt(0))) //error here
println("here")
}

然后是调用语句

val encoding = "utf8"
val datasetName = "InsuranceFraud"
val datasetSeparator = ";"

val sc = new SparkContext("local", "DataValidation Application")

val DataValidation = new DataValidation(datasetPath, datasetName,
datasetSeparator, encoding, sc)

我得到的错误是

Caused by: java.io.NotSerializableException: org.apache.spark.SparkContext
Serialization stack:
    - object not serializable (class: org.apache.spark.SparkContext, value: org.apache.spark.SparkContext@2aa98145)
    - field (class: $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$DataValidation, name: sc, type: class org.apache.spark.SparkContext)
    - object (class $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$DataValidation, $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$DataValidation@3d93cd9c)
    - field (class: $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$DataValidation$$anonfun$1, name: $outer, type: class $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$DataValidation)
    - object (class $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$DataValidation$$anonfun$1, <function1>)
    at org.apache.spark.serializer.SerializationDebugger$.improveException(SerializationDebugger.scala:40)
    at org.apache.spark.serializer.JavaSerializationStream.writeObject(JavaSerializer.scala:47)
    at org.apache.spark.serializer.JavaSerializerInstance.serialize(JavaSerializer.scala:81)
    at org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:312)
    ... 87 more

请注意以下行为

  1. 如果我按如下方式更改类中的语句,那么一切正常。

    val separatorCount = rdd.map(_.count(_ == ';'))

  2. 如果我内联方法,即只执行方法中的语句而没有方法,一切都有效。

1 个答案:

答案 0 :(得分:2)

我现在已经解决了这个问题。

由于我在map函数中使用了分隔符,因此尝试对整个类进行序列化。但是,方法textile_encoding无法序列化导致错误。

因此,我已将此方法移至单独的类并在外部实例化并将其传递给此类。

现在序列化很好。

当你遇到这个问题时,我认为你有三个解决方案: -

  1. 做我做的。将方法移动到其他类
  2. 编写自己的闭包/序列化。 (不知道怎么回事)
  3. 预先列出违规方法(不知道如何)
  4. 此致

    阿梅尔