org.apache.spark.SparkException:任务在scala中不可序列化

时间:2016-09-19 09:42:40

标签: scala apache-spark

我是Scala的新手。我在Spark上执行下面的代码:

scala>   for(line <- sc.textFile("hdfs://ip:8020/property.conf")) 
         {
            val c = line.split("=")
            SparkConf.set(c(0), c(1)) 
            //println(c(0)+" "+c(1))   //Commented
         }

如果我删除评论的部分并评论SparkConf.set(c(0), c(1)),那么它可以正常工作并显示数据。

但在这种情况下,我想在运行时将参数设置为 SparkConf 。 但它让我错误

  

org.apache.spark.SparkException:任务不可序列化

请建议我做点什么。

1 个答案:

答案 0 :(得分:2)

理解spark的一个非常重要的事情是它是一个分布式环境。

名称RDDResilient Distributed Datasets的缩写。 spark RDD中的项目通常分为partitions,它们分布在Spark集群中的各个不同节点上。

当你调用yourRdd.map(a => a.toString)之类的东西时,这个RDD的map实现知道它必须首先将这个a => a.toString函数包装在一个闭包中,然后序列化该闭包然后发送它到具有此partitions RDD的所有节点。结果的实际计算发生在那些节点上。

所以......当你处理RDD时,请确保你不要将分发感知RDD api与普通的Scala api混淆/混合。

编写一段代码的推荐方法是,

val yourRdd = sc.textFile("hdfs://ip:8020/property.conf")) 

yourRdd.foreach(line =>
  val c = line.split("=")
  println(c(0) + " " + c(1))
)

SparkConf.set(c(0), c(1))行中,SparkConfclass,您通常无法序列化classes。你也不能在set上调用成员函数class SparkConf。您需要创建classes的实例。另外SparkConf碰巧是一个没有实现可序列化接口的类,因此即使SparkConf的实例也不可序列化。

通常情况下,您不应该使用spark RDD来创建SparkConf,因为如果没有SparkContext而RDD将不存在,而SparkConf又需要初始化val mySparkConf = new SparkConf() val yourRdd = sc.textFile("hdfs://ip:8020/property.conf")) val yourList = yourRdd.foreach(line => val c = line.split("=") ).collect.toList yourList.foreach(c => mySparkConf.set(c(0), c(1)))

但是对于这种情况,我们可以说你需要这样做...然后你首先从你的RDD获得一个普通的scala列表然后用它来创建你的SparkConf。

.fixed-table-body