问题无法找到 s3ablock-0001- 的任何有效本地目录

Bru*_*des 5 hadoop amazon-emr apache-spark pyspark

当我尝试在 S3 上写入数据时,我在 Amazon EMR 上运行作业时遇到问题。

这是堆栈跟踪:

org.apache.hadoop.util.DiskChecker$DiskErrorException: Could not find any valid local directory for s3ablock-0001-
    at org.apache.hadoop.fs.LocalDirAllocator$AllocatorPerContext.getLocalPathForWrite(LocalDirAllocator.java:463)
    at org.apache.hadoop.fs.LocalDirAllocator$AllocatorPerContext.createTmpFileForWrite(LocalDirAllocator.java:477)
    at org.apache.hadoop.fs.LocalDirAllocator.createTmpFileForWrite(LocalDirAllocator.java:213)
    at org.apache.hadoop.fs.s3a.S3AFileSystem.createTmpFileForWrite(S3AFileSystem.java:589)
    at org.apache.hadoop.fs.s3a.S3ADataBlocks$DiskBlockFactory.create(S3ADataBlocks.java:811)
    at org.apache.hadoop.fs.s3a.S3ABlockOutputStream.createBlockIfNeeded(S3ABlockOutputStream.java:190)
    at org.apache.hadoop.fs.s3a.S3ABlockOutputStream.(S3ABlockOutputStream.java:168)
    at org.apache.hadoop.fs.s3a.S3AFileSystem.create(S3AFileSystem.java:822)
    at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:1125)
    at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:1105)
    at org.apache.parquet.hadoop.util.HadoopOutputFile.create(HadoopOutputFile.java:74)
    at org.apache.parquet.hadoop.ParquetFileWriter.(ParquetFileWriter.java:248)
    at org.apache.parquet.hadoop.ParquetOutputFormat.getRecordWriter(ParquetOutputFormat.java:390)
    at org.apache.parquet.hadoop.ParquetOutputFormat.getRecordWriter(ParquetOutputFormat.java:349)
    at org.apache.spark.sql.execution.datasources.parquet.ParquetOutputWriter.(ParquetOutputWriter.scala:37)
    at org.apache.spark.sql.execution.datasources.parquet.ParquetFileFormat$$anon$1.newInstance(ParquetFileFormat.scala:158)
    at org.apache.spark.sql.execution.datasources.SingleDirectoryDataWriter.newOutputWriter(FileFormatDataWriter.scala:126)
    at org.apache.spark.sql.execution.datasources.SingleDirectoryDataWriter.(FileFormatDataWriter.scala:111)
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$.executeTask(FileFormatWriter.scala:264)
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$.$anonfun$write$15(FileFormatWriter.scala:205)
    at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:90)
    at org.apache.spark.scheduler.Task.run(Task.scala:127)
    at org.apache.spark.executor.Executor$TaskRunner.$anonfun$run$3(Executor.scala:444)
    at org.apache.spark.util.Utils$.tryWithSafeFinally(Utils.scala:1377)
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:447)
    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)

我使用 Amazon ECS for EMR 以及Apache Spark 3.0.1 和 Hadoop 3.2.1构建了一个映像,我已经尝试使用 Apache Spark 2.4.5 和 Hadoop 2.7.1 但没有成功。

当我们在没有 ECS 映像的情况下手动构建 EMR 时,工作成功完成并将所需的所有内容写入 S3 上。

我恳求你们,我需要做什么才能让这些东西启动并运行?多谢。

Ste*_*ran 8

您需要为应用程序提供一个用于存储数据的目录

spark.hadoop.fs.s3a.buffer.dir /tmp,/drive1/tmp
Run Code Online (Sandbox Code Playgroud)

通常它会选择hadoop.tmp.dir所设置的内容。也许您只是没有足够的磁盘空间,或者该选项设置为小根驱动器上的某个位置。

更好:为您拥有的每个磁盘添加一个条目,它将尝试使用任何有足够空间的磁盘。

进一步阅读S3A如何向S3写入数据

在 Hadoop 3.2.1 上,您可以告诉 S3A 在堆或字节缓冲区中进行缓冲,因此根本不使用本地磁盘。

spark.hadoop.fs.s3a.fast.upload.buffer bytebuffer
Run Code Online (Sandbox Code Playgroud)

我们在某些部署中执行此操作,其中进程没有对本地文件系统的写入访问权限和/或没有容量。但随后您需要努力调整其他一些相关参数,以避免缓冲太多数据 - 从 EC2 到 S3 的有限带宽可能会造成大量积压

实际上,这也可能是磁盘缓冲的问题 - 也许您只是创建数据的速度快于上传数据的速度。尝试限制单个输出流(此处:spark 工作线程)在流写入块之前可以排队等待上传的块数:

spark.hadoop.fs.s3a.fast.upload.active.blocks 1
Run Code Online (Sandbox Code Playgroud)

该数量和/或更少数量的工作线程。

请更新这篇文章,无论是否有效,以便其他人可以使用您的发现