在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-18t4:56:51.601135#25683〕信息-:attempt_20130111840_142285_r_ 000009_0:在org.apache.hoop.hdfs.DFSClient.checkOpen(DFSClient.java)
I、 〔2013-11-18t4:56:51.601168#25683〕信息-:attempt_20130111840_142285_r_ 000009_0:在org.apache.hoop.hdfs.DFSInputStream.close(DFSInput Stream.java:522)
I、 〔2013-11-18t4:56:51.601199#25683〕信息-:attempt_20130111840_142285_r_ 000009_0:在java.io.FilterInputStream.close(FilterInputStream.java:155)
I、 〔2013-11-18t4:56:51.601230#25683〕信息-:attempt_20130111840_142285_r_ 000009_0:在sun.nio.cs.StreamDecoder.implClose(StreamDecoder.java:358)
I、 〔2013-11-18t4:56:51.601263#25683〕信息-:attempt_20130111840_142285_r_ 000009_0:在sun.nio.csStreamDecoder.close(StreamDecoder.java:173)
I、 〔2013-11-18t4:56:51.601356#25683〕信息-:attempt_20130111840_142285_r_ 000009_0:在java.io.InputStreamReader.close(InputStreamReader.java:182)
I、 〔2013-11-18t4:56:51.601395#25683〕信息-:attempt_20130111840_142285_r_ 000009_0:在java.io.BufferedReader.close(BufferedReader.java:497)
我不知道为什么会发生这种异常情况。这不是多线程的,所以我不希望有任何形式的竞争条件。你能帮我理解吗。
谢谢,
Venk
hadoop文件系统API有一个鲜为人知的问题:FileSystem.get
对同一文件系统的每次调用都返回相同的对象。因此,如果一个在任何地方都关闭了,那么它们都是关闭的。你可以争论这个决定的优点,但事实就是这样
因此,如果您试图关闭BufferedReader,并且它试图清空它缓冲的一些数据,但底层流连接到一个已经关闭的文件系统,则会出现此错误。检查您的代码中关闭FileSystem对象的任何其他位置,并查找竞争条件。此外,我相信Hadoop本身会在某个时候关闭FileSystem,因此为了安全起见,您可能只应该从Reducer的设置、减少或清理方法中访问它(或者配置、减少和关闭,取决于您使用的API)。
您必须使用FileSystem.newInstance
来避免使用共享连接(如Joe K所述)。它将为您提供一个唯一的、非共享的实例。