Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 带检查点的Spark会话空指针_Scala_Apache Spark_Spark Streaming_Checkpointing - Fatal编程技术网

Scala 带检查点的Spark会话空指针

Scala 带检查点的Spark会话空指针,scala,apache-spark,spark-streaming,checkpointing,Scala,Apache Spark,Spark Streaming,Checkpointing,我启用了将日志保存到S3的检查点。 如果检查点目录中没有文件,spark streaming工作正常,我可以看到日志文件出现在检查点目录中。然后我杀死spark streaming并重新启动它。这一次,我开始为spark会话获取NullPointerException。 简而言之,如果检查点目录中没有日志文件,spark streaming可以正常工作。但是,只要我使用检查点目录中的日志文件重新启动spark streaming,spark会话上就会出现空指针异常。 代码如下: object a

我启用了将日志保存到S3的检查点。 如果检查点目录中没有文件,spark streaming工作正常,我可以看到日志文件出现在检查点目录中。然后我杀死spark streaming并重新启动它。这一次,我开始为spark会话获取NullPointerException。 简而言之,如果检查点目录中没有日志文件,spark streaming可以正常工作。但是,只要我使用检查点目录中的日志文件重新启动spark streaming,spark会话上就会出现空指针异常。 代码如下:

object asf {
  val microBatchInterval = 5
  val sparkSession = SparkSession
    .builder()
    .appName("Streaming")
    .getOrCreate()

    val conf = new SparkConf(true)
    //conf.set("spark.streaming.receiver.writeAheadLog.enable", "true")
    val sparkContext = SparkContext.getOrCreate(conf)


  val checkpointDirectory = "s3a://bucketname/streaming-checkpoint"

  println("Spark session: " + sparkSession)

  val ssc = StreamingContext.getOrCreate(checkpointDirectory,
    () => {
      createStreamingContext(sparkContext, microBatchInterval, checkpointDirectory, sparkSession)
    }, s3Config.getConfig())

  ssc.start()
  ssc.awaitTermination()
}

  def createStreamingContext(sparkContext: SparkContext, microBatchInterval: Int, checkpointDirectory: String,spark:SparkSession): StreamingContext = {
    println("Spark session inside: " + spark)
    val ssc: org.apache.spark.streaming.StreamingContext = new StreamingContext(sparkContext, Seconds(microBatchInterval))
    //TODO: StorageLevel.MEMORY_AND_DISK_SER
    val lines = ssc.receiverStream(new EventHubClient(StorageLevel.MEMORY_AND_DISK_SER);
    lines.foreachRDD {
      rdd => {
        val df = spark.read.json(rdd)
        df.show()
      }
    }
    ssc.checkpoint(checkpointDirectory)
    ssc
  }
}  
同样,在我第一次运行这段代码时(检查点目录中没有日志文件),我可以看到数据帧被打印出来。 如果我使用检查点目录中的日志文件运行,我甚至看不到

println("Spark session inside: " + spark)
第一次打印出来。错误:

Exception in thread "main" java.lang.NullPointerException
    at org.apache.spark.sql.SparkSession.sessionState$lzycompute(SparkSession.scala:111)
    at org.apache.spark.sql.SparkSession.sessionState(SparkSession.scala:109)
    at org.apache.spark.sql.DataFrameReader.<init>(DataFrameReader.scala:549)
    at org.apache.spark.sql.SparkSession.read(SparkSession.scala:605)
编辑:我添加了这一行:

conf.set("spark.streaming.stopGracefullyOnShutdown","true")

这仍然没有什么区别,仍然得到NullPointerException。

回答我自己的问题,这是有效的:

lines.foreachRDD {
  rdd => {
    val sqlContext:SQLContext = SparkSession.builder.config(rdd.sparkContext.getConf).getOrCreate().sqlContext

    val df = sqlContext.read.json(rdd)
    df.show()
  }
}

通过从rdd.sparkContext构建的spark会话,这是一种反模式。为了让新手明确受益,spark会话可以工作。不允许在转换内创建数据集


正如Michel提到的,executor无法访问SparkSession

您是否在运行之间更改了代码?设置检查点时不能更改代码。如果是这种情况,请参阅相关spark文档。您需要优雅地关闭并删除或更改检查点dir每次我第一次运行作业时,我都会清空s3a://bucketname/streaming checkpoint。然后我会按Ctrl+C关闭spark streaming。然后再次启动,然后我会得到空指针异常。我在RunsinDect之间使用了相同的代码,这解释了很多。。当代码在执行器上运行时,它无权访问val
spark
。我很惊讶你没有得到一个任务不可序列化的异常。请进一步挖掘,
sessionState
是一个暂时的惰性val。这意味着每个执行器上都有一个用于初始化变量的插槽。它与驱动程序上的实例不共享同一个实例。因为它是惰性的,所以它在第一次使用时得到初始化,而第一次使用恰好是在您加载检查点时。此时,它尝试使用另一个val
parentSessionState
,该值在执行器上为null,因为它也是暂时的。当我在sqlContext.read.json之后添加第二个类的另一行处理时,问题实际上会出现。例如,我在forEachRDD之外实例化了这个二级类,它所采用的参数之一是在实例化时使用sparkSession。在第二节课中,我使用sparkSession做了一些spark.sql之类的事情。这基本上意味着我必须在forEachRDD中每次实例化这个二级类,以从RDD获取spark会话。。。
lines.foreachRDD {
  rdd => {
    val sqlContext:SQLContext = SparkSession.builder.config(rdd.sparkContext.getConf).getOrCreate().sqlContext

    val df = sqlContext.read.json(rdd)
    df.show()
  }
}