Hadoop-HDFS DFSClient的严重bug

上一篇说到Shell 对自身DN造成的性能影响,本篇说一下它对DFSClient的冲击。

不知道有没有朋友像我这样病态的使用Hadoop, 我的DFSClient总是一直Running的,因为我需要它时刻为我做事,所以我不会轻意重新创建一个与NN相连的DFSClient。 闲言少述。

Shell 的执行对正在put文件的客户端会产生下列异常:
1. DataStreamer Exception: java.io.IOException: Unable to create new block.
该异常是由Bad connect ack with firstBadLink:h1 异常引起的, 意思是说在传输下一个BLOCK的时候,DFSClient会建立向DN的一个传输管道,那么在传输真实chunk数据之前,需要各个节点对于管道中头信息的确认给予DFSClient反馈,节点h1 给予了错误的反馈信息,或压根就没有收到h1的ack. 这种情况有必要说一下,在任意多节点的情况下,该问题可以被DFSClient 容错。

关闭文件流时产生下列异常:
1. Error Recovery for block blk_-XXXX_XXXX bad datanode[X] nodes == null
不可否认, 这异常同样是由于DN的不稳定,在客户端ResponseProcessor的处理中,抛出的。Hadoop的DFSClient通过ResponseProcessor类,从DN的输入流中读取包的反馈ack值, 如果ack值不正确, ackQueue对列中的Packet就不会被移除, 而是通过DataStream类尝试发送。

有意思的一幕随着关闭文件流产生的异常而发生, DFSClient中的FSOutputStream#close() 方法:
public void close() throws IOException {
      if(closed)
        return;
      closeInternal();
      leasechecker.remove(src);
      
      if (s != null) {
        s.close();
        s = null;
      }
    }

在执行close方法时, closeInternal() 方法显然已经抛出了上面我们说到的异常, 那么socket.close() 这句就未执行到。

很有趣的现象:我用dfshealth.jsp页面把DN的Xceiver值输出, 发现该值在运行一段时间后会变的奇高,stack中可以看到DN存在很多reciverPacket() 的线程, 但DFSClient端的stack就是看不到任何sendPacket之类的线程,跑到heap中, 才能看到有不少socket对象。
这个bug已经由hadoop-0.21-trunk在解决, 如果使用低版本的朋友, 可以手动try一下closeInternal() 方法。 但即使关闭socket, 还是无法稳定文件block的, 除非Shell问题得到彻底解决。

你可能感兴趣的:(hadoop,log4j,jsp,socket)