在Reduce设置方法中,我尝试关闭BufferedReader
对象并获得FileSystem
已关闭的异常。它不会一直发生。这是我用来创建BufferedReader
。
String fileName = <some HDFS file path>
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path hdfsPath = new Path(filename);
FSDataInputStream in = fs.open(hdfsPath);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
我从bufferedReader读取内容,一旦完成所有读取,我就关闭它。
这是读取它的代码
String line;
while ((line = reader.readLine()) != null) {
// Do something
}
这段关闭读者的代码。
if (bufferedReader != null) {
bufferedReader.close();
}
这是我执行bufferedReader.close()
时发生的异常的堆栈跟踪。
I,[2013-11-18T04:56:51.601135#25683]信息 - : attempt_201310111840_142285_r_000009_0:at org.apache.hadoop.hdfs.DFSClient.checkOpen(DFSClient.java:565)
I,[2013-11-18T04:56:51.601168#25683]信息 - : attempt_201310111840_142285_r_000009_0:at org.apache.hadoop.hdfs.DFSInputStream.close(DFSInputStream.java:522)
I,[2013-11-18T04:56:51.601199#25683]信息 - : attempt_201310111840_142285_r_000009_0:at java.io.FilterInputStream.close(FilterInputStream.java:155)
I,[2013-11-18T04:56:51.601230#25683]信息 - : attempt_201310111840_142285_r_000009_0:at sun.nio.cs.StreamDecoder.implClose(StreamDecoder.java:358)
I,[2013-11-18T04:56:51.601263#25683]信息 - : attempt_201310111840_142285_r_000009_0:at sun.nio.cs.StreamDecoder.close(StreamDecoder.java:173)
I,[2013-11-18T04:56:51.601356#25683]信息 - : attempt_201310111840_142285_r_000009_0:at java.io.InputStreamReader.close(InputStreamReader.java:182)
I,[2013-11-18T04:56:51.601395#25683]信息 - : attempt_201310111840_142285_r_000009_0:at java.io.BufferedReader.close(BufferedReader.java:497)
我不确定为什么会发生这种异常。这不是多线程的,因此,我不认为会出现任何形式的竞争条件。能帮助我理解吗。
谢谢,
Venk
答案 0 :(得分:32)
hadoop文件系统API有一个鲜为人知的问题:FileSystem.get
为每个具有相同文件系统的调用返回相同的对象。因此,如果一个人在任何地方关闭,他们都会关闭。你可以辩论这个决定的优点,但这就是它的方式。
因此,如果您尝试关闭BufferedReader,并尝试清除缓冲的某些数据,但基础流连接到已关闭的FileSystem,您将收到此错误。检查代码中是否有关闭FileSystem对象的其他位置,并查找竞争条件。另外,我相信Hadoop本身会在某些时候关闭FileSystem,所以为了安全起见,你应该只能从Reducer的setup,reduce或cleanup方法中访问它(或者配置,减少和关闭,具体取决于哪个API)你正在使用。)
答案 1 :(得分:16)
您必须使用FileSystem.newInstance
来避免使用共享连接(如Joe K所述)。它将为您提供一个独特的非共享实例。