数据堆上的Spark流抛出FileNotFoundException

时间:2016-12-13 01:01:43

标签: apache-spark google-cloud-dataproc

当我尝试向Google Dataproc群集提交火花流式传输作业时,我遇到了以下异常:

16/12/13 00:44:20 ERROR org.apache.spark.SparkContext: Error initializing SparkContext.
java.io.FileNotFoundException: File file:/tmp/0afbad25-cb65-49f1-87b8-9cf6523512dd/skyfall-assembly-0.0.1.jar does not exist
        at org.apache.hadoop.fs.RawLocalFileSystem.deprecatedGetFileStatus(RawLocalFileSystem.java:611)
        at org.apache.hadoop.fs.RawLocalFileSystem.getFileLinkStatusInternal(RawLocalFileSystem.java:824)
...
16/12/13 00:44:20 INFO org.spark_project.jetty.server.ServerConnector: Stopped ServerConnector@d7bffbc{HTTP/1.1}{0.0.0.0:4040}
16/12/13 00:44:20 WARN org.apache.spark.scheduler.cluster.YarnSchedulerBackend$YarnSchedulerEndpoint: Attempted to request executors before the AM has registered!
16/12/13 00:44:20 ERROR org.apache.spark.util.Utils: Uncaught exception in thread main
java.lang.NullPointerException
        at org.apache.spark.network.shuffle.ExternalShuffleClient.close(ExternalShuffleClient.java:152)
        at org.apache.spark.storage.BlockManager.stop(BlockManager.scala:1360)
...
Exception in thread "main" java.io.FileNotFoundException: File file:/tmp/0afbad25-cb65-49f1-87b8-9cf6523512dd/skyfall-assembly-0.0.1.jar does not exist
        at org.apache.hadoop.fs.RawLocalFileSystem.deprecatedGetFileStatus(RawLocalFileSystem.java:611)
        at org.apache.hadoop.fs.RawLocalFileSystem.getFileLinkStatusInternal(RawLocalFileSystem.java:824)

完整输出here

如果在spark-env.sh中未正确定义hadoop配置,则会发生此错误 - link1link2

可以在某处配置吗?有关如何解决它的任何指示?

在本地模式下运行相同的代码可以正常工作:

sparkConf.setMaster("local[4]")

对于其他上下文:作业被调用如下:

gcloud dataproc jobs submit spark \
--cluster my-test-cluster \
--class com.company.skyfall.Skyfall \
--jars gs://my-bucket/resources/skyfall-assembly-0.0.1.jar \
--properties spark.ui.showConsoleProgress=false

这是样板设置代码:

  lazy val conf = {
    val c = new SparkConf().setAppName(this.getClass.getName)
    c.set("spark.ui.port", (4040 + scala.util.Random.nextInt(1000)).toString)

    if (isLocal) c.setMaster("local[4]")
    c.set("spark.streaming.receiver.writeAheadLog.enable", "true")
    c.set("spark.streaming.blockInterval", "1s")
  }

  lazy val ssc = if (checkPointingEnabled) {
    StreamingContext.getOrCreate(getCheckPointDirectory, createStreamingContext)
  } else {
    createStreamingContext()
  }

  private def getCheckPointDirectory: String = {
    if (isLocal) localCheckPointPath else checkPointPath
  }

  private def createStreamingContext(): StreamingContext = {
    val s = new StreamingContext(conf, Seconds(batchDurationSeconds))
    s.checkpoint(getCheckPointDirectory)
    s
  }

提前致谢

2 个答案:

答案 0 :(得分:1)

这可能是您第一次使用给定的检查点目录运行作业,因为检查点目录中已包含检查点吗?

这是因为检查点对用于提交YARN应用程序的确切jarfile参数进行硬编码,并且在Dataproc上运行时指向GCS的--jars标志,这实际上是Dataproc的语法糖,自动暂存您的jar文件从GCS到本地文件路径/tmp/0afbad25-cb65-49f1-87b8-9cf6523512dd/skyfall-assembly-0.0.1.jar,它仅在单个作业运行期间暂时使用,因为Spark无法直接从GCS调用jar文件而无需在本地暂存。

但是,在后续作业中,先前的tmp jar文件已被删除,但新作业会尝试引用硬编码到检查点数据中的旧位置。

检查点数据中的硬编码还会导致其他问题;例如,Dataproc还使用YARN“标签”来跟踪作业,如果旧的Dataproc作业的“标签”在新的YARN应用程序中重用,则会与YARN冲突。要运行流应用程序,您需要首先清除检查点目录,如果可能的话,从干净的平板开始,然后:

  1. 在开始作业之前,必须将作业jar文件放在主节点上的某个位置,然后“--jar”标志必须指定“file:///path/on/master/node/to/jarfile.jar”
  2. 当你指定一个“file:///”路径时,dataproc知道它已经在主节点上,所以它不会重新进入/ tmp目录,因此在这种情况下,检查点可以安全地指向某个修复了主服务器上的本地目录。

    您可以使用init操作执行此操作,也可以提交快速pig作业(或者只是ssh到master中并下载该jar文件):

    # Use a quick pig job to download the jarfile to a local directory (for example /usr/lib/spark in this case)
    gcloud dataproc jobs submit pig --cluster my-test-cluster \
        --execute "fs -cp gs://my-bucket/resources/skyfall-assembly-0.0.1.jar file:///usr/lib/spark/skyfall-assembly-0.0.1.jar"
    
    # Submit the first attempt of the job
    gcloud dataproc jobs submit spark --cluster my-test-cluster \
        --class com.company.skyfall.Skyfall \
        --jars file:///usr/lib/spark/skyfall-assembly-0.0.1.jar \
        --properties spark.ui.showConsoleProgress=false
    
    1. Dataproc依赖于引擎盖下的spark.yarn.tags来跟踪与作业相关联的YARN应用程序。但是,检查点包含一个陈旧的spark.yarn.tags,这会导致Dataproc与似乎与旧作业相关的新应用程序混淆。
    2. 目前,它只会“清理”可疑的YARN应用程序,只要最近被杀死的jobid保存在内存中,因此重新启动数据交换器代理将解决此问题。

      # Kill the job through the UI or something before the next step.
      # Now use "pig sh" to restart the dataproc agent
      gcloud dataproc jobs submit pig --cluster my-test-cluster \
          --execute "sh systemctl restart google-dataproc-agent.service"
      
      # Re-run your job without needing to change anything else,
      # it'll be fine now if you ever need to resubmit it and it
      # needs to recover from the checkpoint again.
      

      请注意,虽然检查点本质上意味着您将无法更改在后续运行中传递的参数,因为检查点恢复用于破坏您的命令行设置。

答案 1 :(得分:0)

您还可以在纱线群集模式下运行作业,以避免将jar添加到主计算机。潜在的权衡是火花驱动程序将在工作节点而不是主节点中运行。