为什么DStream.foreachRDD会因java.io.NotSerializableException而失败:org.apache.spark.SparkContext?

时间:2017-06-26 06:10:42

标签: apache-spark apache-kafka spark-streaming spark-graphx

我需要根据来自Kafka的处理数据使用GraphX构建图形。但是,似乎sc.parallelize()引发了错误java.io.NotSerializableException: org.apache.spark.SparkContext

......
val messages = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](
  ssc, kafkaParams, topicsSet)
val lines = messages.map(_._2)

lines.foreachRDD(rdd => {
  rdd.foreachPartition(partition => {
    ......
    // Build a graph
    val vertRDD = sc.parallelize(vertices)
    val edgeRDD = sc.parallelize(edge)
    val graph = Graph(vertRDD, edgeRDD, defaultUser)
    }
  })
})

我应该以什么方式解决问题?

1 个答案:

答案 0 :(得分:1)

Spark Streaming中的

foreachRDD运算符在驱动程序上每个批处理间隔运行处理RDD,然后使用它(通过其RDD)来编写最终将自身转换为Spark作业的代码。

  

foreachRDD(foreachFunc:(RDD [T])⇒单位):单位将一个函数应用于此DStream中的每个RDD。这是一个输出操作符,因此'this'DStream将被注册为输出流,因此具体化。

RDD.foreachPartition是一种只会在执行者身上发生的动作。

  

foreachPartition(f:(Iterator [T])⇒Unit):Unit 将函数f应用于此RDD的每个分区。

在任务可以在执行程序上执行之前,它必须被序列化,因为SparkContext不可序列化,因此是例外。这就是Spark如何确保SparkContext(因为sc)永远不会出现由于Spark中的设计决策。这无论如何都没有意义,因为整个调度基础设施都在驱动程序上。

SparkContextRDD仅适用于驱动程序。它们只是描述分布式计算的一种方式,最终将“转换”为在Spark执行程序上运行的任务。

这就是您看到错误消息的原因:

  

java.io.NotSerializableException:org.apache.spark.SparkContext

顺便说一下,我今天回答了类似的问题(见Can SparkContext.textFile be used with a custom receiver?),所以看起来今天是SparkContext日:)