AWS EMR Spark集群主节点文件存在但Yarn运行时报不存在错误
问题原因
- 执行位置差异:你代码里的
os.listdir、路径打印逻辑是在**Driver进程(运行在EMR主节点)**执行的,读取的是主节点本地磁盘的内容,所以可以正常识别到文件路径。 - 读取逻辑与路径协议问题:
spark.read.load操作由运行在Worker节点的Executor进程执行,且你没有给路径指定本地文件协议file://,Spark在YARN模式下默认会优先去HDFS查找对应路径的文件。两个问题叠加导致报错:要么HDFS上不存在该路径,要么Worker节点本地没有对应文件。
你猜测的「没有将文件拷贝到Worker节点」确实是核心原因之一,同时还有路径协议的问题。
解决方案
推荐优先使用方案1,符合Spark分布式处理的设计:
方案1:将文件上传到HDFS(推荐)
所有Executor都可以直接访问HDFS上的公共存储,不需要同步文件到每台Worker:
- 在主节点执行命令将本地目录上传到HDFS:
hdfs dfs -put /home/hadoop/sas_data1 /user/hadoop/
- 修改代码中的
sas_dir为HDFS路径即可:
sas_dir = '/user/hadoop/sas_data1'
方案2:坚持使用本地磁盘存储
需要同时完成两个操作:
- 将
sas_data1目录原样拷贝到集群所有Worker节点的/home/hadoop/路径下 - 读取文件时给路径加上
file://前缀,明确指定读取本地磁盘,不要走HDFS:
df_spark = spark.read.format('com.github.saurfang.sas.spark').\ load(f'file://{sas_dir}/{filename}')
方案3:小文件场景适配
如果你的SAS文件总大小小于100M,可以在spark-submit命令中加上--files sas_data1/file1.sas7bdat,sas_data1/file2.sas7bdat参数,提交任务时将文件同步到所有Executor的工作目录,直接传文件名读取即可。该方案不适合你当前1G大小的文件场景。
内容的提问来源于stack exchange,提问作者H P
相关产品推荐
相关产品推荐

