FileSystem.get从缓存cache中获得连接导致的问题

首先了解FileSyste.get机制,查看源码可知,首先会根据fs.hdfs.impl.disable.cache,是否去缓存cache中找连接,默认是去缓存中找连接的,参考:HDFS下载数据之源码分析-FileSystem.get(conf)_block01

所以就存在复用FileSystem的情况,当复用FileSystem时,如果多线程都有关闭FileSystem,就会报错,提示Filesystem closed,最后一行是DFSClient.checkOpen。这是因为这个方法会去判断如果FileSystem已经关闭,就会抛出一个异常。

 java.io.IOException: Filesystem closed
        at org.apache.hadoop.hdfs.DFSClient.checkOpen(DFSClient.java:795)

由上面所导致的情况有多种,下面就是2种比较典型的

1.当Spark和HDFS api同时存在时,当你的hdfs api去调用FileSystem的close方法时,会报上面的错误,因为他们都是去cache中获取连接,而你的api close了fileSystem,导致spark的hdfs连接不能用。所以会报错。

参考:hadoop/spark关闭钩子研究

2.hadoop运行mapreduce任务时,由于多个datanode节点需要读取hdfs filesystem,此时,如果一个节点因为网络或者其他原因关掉了该filesystem,而其他节点仍然使用的cache中的filesystem,导致触发IOException

出现这个问题是在hive使用的时候出现的

参考:hive查询hdfs数据时,遇到的两个hadoop配置问题

3.hive由fs.hdfs.impl.disable.cache参数引起的重写分区数据的异常

解决方案:fs.hdfs.impl.disable.cache使用默认值,也就是false。每种情况下面再细细分析。

分析情况:

情况1:这里是spark和hdfs api共用导致的,并不是hadoop的设计缺陷,只是你后去spark和hdfs api没有协调好,没有用好,所以建议在hdfs api中不close任何东西,等spark集群去close。

情况2:打开参考的那么文章,有这么一句,“如果一个节点因为网络或者其他原因”,这是因为外部原因,hadoop系统本身设计是没有问,所以这里应该让hive或者mapreduce优化FileSystem的使用方式。

情况3:如果将fs.hdfs.impl.disable.cache改变了,那么情况3的问题就会出现。因为官方的core-site.xml都没有出现这个属性,所以我们不能轻易的去改变他。

所以最后选择哪种方法,只能自己去权衡了。建议不要修改fs.hdfs.impl.disable.cache属性。

 

 

 

 

 

 

你可能感兴趣的:(FileSystem.get从缓存cache中获得连接导致的问题)