Spark 工作线程在临时随机文件上抛出 FileNotFoundException

Cal*_*ity 5 scala apache-spark

我正在运行一个处理多组数据点的 Spark 应用程序;其中一些集合需要按顺序处理。当针对小型数据点集(大约 100 个)运行应用程序时,一切正常。但在某些情况下,集合的大小约为。10,000 个数据点,这些会导致工作线程崩溃并显示以下堆栈跟踪:

Exception in thread "main" org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 26.0 failed 4 times, most recent failure: Lost task 0.3 in stage 26.0 (TID 36, 10.40.98.10, executor 1): java.io.FileNotFoundException: /tmp/spark-5198d746-6501-4c4d-bb1c-82479d5fd48f/executor-a1d76cc1-a3eb-4147-b73b-29742cfd652d/blockmgr-d2c5371b-1860-4d8b-89ce-0b60a79fa394/3a/temp_shuffle_94d136c9-4dc4-439e-90bc-58b18742011c (No such file or directory)
    at java.io.FileOutputStream.open0(Native Method)
    at java.io.FileOutputStream.open(FileOutputStream.java:270)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
    at org.apache.spark.storage.DiskBlockObjectWriter.initialize(DiskBlockObjectWriter.scala:102)
    at org.apache.spark.storage.DiskBlockObjectWriter.open(DiskBlockObjectWriter.scala:115)
    at org.apache.spark.storage.DiskBlockObjectWriter.write(DiskBlockObjectWriter.scala:235)
    at org.apache.spark.shuffle.sort.BypassMergeSortShuffleWriter.write(BypassMergeSortShuffleWriter.java:151)
    at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:96)
    at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:53)
    at org.apache.spark.scheduler.Task.run(Task.scala:108)
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:335)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Run Code Online (Sandbox Code Playgroud)

我在多次出现此错误后检查了所有日志文件,但没有找到任何其他错误消息。

在网上搜索这个问题,我发现了两个似乎不适用于我的情况的潜在原因:

  • 运行Spark进程的用户对该目录没有读写权限/tmp/
    • 鉴于错误仅发生在较大的数据集上(而不是总是发生),我不认为这会成为问题。
  • /tmp/目录没有足够的空间来容纳随机文件(或其他临时 Spark 文件)。
    • 我的系统上的目录/tmp/大约有 45GB 可用空间,单个数据点中的数据量 (< 1KB) 意味着情况也可能并非如此。

我已经在这个问题上挣扎了几个小时,试图找到解决方法和可能的原因。

  • 我尝试将集群(通常是两台机器)减少为单个工作程序,与驱动程序在同一台机器上运行,希望这能够消除洗牌的需要,从而防止此错误。这没有用;错误以完全相同的方式发生。
  • 我已将问题隔离为通过尾递归方法顺序处理数据集的操作。

是什么导致了这个问题?我该如何自行确定原因?

Cal*_*ity 3

事实证明,问题是工作线程上发生了堆栈溢出(哈!)。

凭直觉,我重写了完全在驱动程序上执行的操作(有效地禁用了 Spark 功能)。当我运行这段代码时,系统仍然崩溃,但现在显示了一个StackOverflowError. 与我之前的看法相反,显然尾递归方法肯定会导致堆栈溢出,就像任何其他形式的递归一样。将方法重写为不再使用递归后,问题就消失了。

堆栈溢出可能不是唯一可能产生原始 FileNotFoundException 的问题,但进行临时代码更改以将操作拉至驱动程序似乎是确定问题实际原因的好方法。