問題描述
我們在用Spark ThriftServer(以下簡稱STS)用在查詢平臺時,遇到了以下報錯:
ERROR SparkExecuteStatementOperation: Error executing query, currentState RUNNING,
org.apache.spark.sql.AnalysisException: org.apache.hadoop.hive.ql.metadata.HiveException: Unable to move source hdfs://nameservice1/tmp/hive/spark-root_hive_2019-06-28_14-43-11_836_5887471809974605195-2/-ext-10000/part-00000-8dbc4e2a-5844-4c44-bf55-8983b49be8b2-c000.snappy to destination hdfs://nameservice1/user/hive/warehouse/test.db/zyz/part-00000-8dbc4e2a-5844-4c44-bf55-8983b49be8b2-c000.snappy;
at org.apache.spark.sql.hive.HiveExternalCatalog.withClient(HiveExternalCatalog.scala:106)
at org.apache.spark.sql.hive.HiveExternalCatalog.loadTable(HiveExternalCatalog.scala:843)
at org.apache.spark.sql.catalyst.catalog.ExternalCatalogWithListener.loadTable(ExternalCatalogWithListener.scala:159)
無法移動文件,有種可能是因爲起服務的用戶在hdfs上沒有相應的文件操作權限,但這個case不是,繼續看:
Caused by: java.io.IOException: Filesystem closed
at org.apache.hadoop.hdfs.DFSClient.checkOpen(DFSClient.java:798)
at org.apache.hadoop.hdfs.DFSClient.getEZForPath(DFSClient.java:2966)
at org.apache.hadoop.hdfs.DistributedFileSystem.getEZForPath(DistributedFileSystem.java:1906)
at org.apache.hadoop.hdfs.client.HdfsAdmin.getEncryptionZoneForPath(HdfsAdmin.java:262)
at org.apache.hadoop.hive.shims.Hadoop23Shims$HdfsEncryptionShim.isPathEncrypted(Hadoop23Shims.java:1221)
at org.apache.hadoop.hive.ql.metadata.Hive.moveFile(Hive.java:2607)
... 50 more
看到這裏就奇怪了,爲什麼hdfs的連接會被關閉呢?
查了一下jira 發現之前也有哥們遇到了:[SPARK-21067]
上面還詳細的寫了重現步驟!
排查過程
順着堆棧,先搞清楚異常是怎麼拋出的:
hive.moveFile:
再跟進Hadoop23Shims.isPathEncrypted:
繼續往下看DFSClient.getEZForPath:
發現了這個checkOpen:
那麼clientRunning什麼時候會被設爲false呢?
答案是在關閉該FileSystem的時候,會調用這個close。
那麼爲什麼關閉一個Session後,新建的Session的FileSystem也已經Closed狀態了呢?
看到org/apache/hadoop/fs/FileSystem.java中有一個Cache:
CACHE具體用處:
很顯然,如果disable.cache爲false,那麼會直接從CACHE中get一個FileSystem然後返回。
也就是說,我們在Spark Conf中的hive-site.xml中加上參數fs.hdfs.impl.disable.cache=true即可。
至此問題解決!
筆者也會在日後將此解決方案分享給社區。