HDP Sandbox中Spark YARN模式saveAsTable报错及Hive表不可见问题
问题排查与解决方案
让我一步步帮你解决这两个棘手的问题:
1. 为什么Local模式正常,YARN模式抛出IOException?
核心原因
你的代码里的文件操作逻辑在YARN集群环境下存在几个关键问题:
- 权限不匹配:Local模式下你大概率是用
root用户运行的,能访问/root/目录,但YARN集群的任务通常是以yarn用户或者提交任务的普通用户运行的,这些用户没有权限读取/root/下的文件,直接导致IO异常。 - 资源路径错误:
this.getClass.getClassLoader.getResource(".").getFile在Local模式下能拿到本地classpath的路径,但在YARN模式下,你的代码是打包在jar里运行的,getResource(".").getFile拿到的是jar内部的路径,无法直接当作本地文件访问。 - 本地文件依赖:你试图从本地
/root/目录拷贝文件到HDFS,但YARN容器里根本不存在这个本地目录(或者没有权限访问)。
修复方案
(1)修改资源读取逻辑,避免依赖本地目录
把csv文件打包到jar的resources目录下,用流的方式读取,而不是直接访问本地文件:
// 替换原来的copyStreamToHdfs逻辑,直接从classpath读取资源流 def copyResourceToHdfs(hdfs: FileSystem, hdfsPath: String, resourceName: String): Unit = { val inputStream = this.getClass.getClassLoader.getResourceAsStream(resourceName) if (inputStream == null) { throw new FileNotFoundException(s"Resource $resourceName not found in jar's resources") } val outputPath = new Path(hdfsPath) if (!hdfs.exists(outputPath)) { val outputStream = hdfs.create(outputPath) org.apache.commons.io.IOUtils.copy(inputStream, outputStream) // 记得关闭流 inputStream.close() outputStream.close() println(s"Successfully copied $resourceName to $hdfsPath") } } // 调用示例 dataList.map(path => { val resourceName = s"${path._1}.${path._2}" val hdfsFile = s"$csvDataDir/${path._1}.${path._2}" copyResourceToHdfs(hdfs, hdfsFile, resourceName) })
(2)确保HDFS路径权限正确
执行以下命令给HDFS的临时目录设置合适的权限(生产环境建议更严谨的权限控制,这里先测试):
hdfs dfs -mkdir -p /tmp/data hdfs dfs -chmod 777 /tmp/data
(3)查看YARN日志定位具体错误
如果还是报错,通过YARN应用ID查看详细日志,能精准定位是哪个文件操作出问题:
yarn logs -applicationId <你的YARN应用ID>
2. 为什么Spark看不到Hive中创建的表?
核心原因
你的SparkSession没有启用Hive支持,导致它用的是Spark内置的元数据存储(Derby数据库),而不是Hive的元数据库(比如MySQL/PostgreSQL),两者的元数据是完全隔离的,自然看不到Hive里创建的表。
另外,你设置executor数为0是无效的——YARN模式下至少需要1个executor才能运行任务,这个操作只会让任务失败,和看不到表没有关系。
修复方案
(1)修改SparkSession创建代码,启用Hive支持
这是最关键的一步,必须添加.enableHiveSupport():
val spark = SparkSession.builder() .enableHiveSupport() // 启用Hive元数据连接 .getOrCreate()
(2)确保Spark能读取Hive配置
集群的$SPARK_HOME/conf目录下必须有hive-site.xml文件,这个文件包含了Hive元数据库的连接信息,Spark需要通过它来访问Hive的元数据。如果没有,从Hive的$HIVE_HOME/conf目录拷贝一份到Spark的conf目录。
(3)测试Spark与Hive的连通性
在spark-shell里执行以下命令,验证是否能看到Hive表:
spark.sql("SHOW TABLES IN default").show()
如果能看到geolocation表,说明配置没问题;如果看不到,检查hive-site.xml里的元数据库连接信息是否正确,以及Spark是否有权限访问元数据库。
内容的提问来源于stack exchange,提问作者Fabio
相关产品推荐
相关产品推荐

