linux下用java读取远程hdfs文件

xggvc2p6  于 2021-06-03  发布在  Hadoop
关注(0)|答案(3)|浏览(507)

我在简单的hadoop安装中遇到了一些问题。我已经下载了hadoop2.4.0并安装在一个centoslinux节点(虚拟机)上。我已经为一个节点配置了hadoop,并在apache站点上描述了伪分布(http://hadoop.apache.org/docs/r2.4.0/hadoop-project-dist/hadoop-common/singlecluster.html). 它从日志中没有任何问题开始,我可以使用命令行中的“hadoopfs”命令读写文件。
我正试图用javaapi从远程机器上的hdfs读取一个文件。机器可以连接并列出目录内容。它还可以确定是否存在包含以下代码的文件:

Path p=new Path("hdfs://test.server:9000/usr/test/test_file.txt");
FileSystem fs = FileSystem.get(new Configuration());
System.out.println(p.getName() + " exists: " + fs.exists(p));

系统打印“true”表示它存在。但是,当我尝试读取文件时:

BufferedReader br = null;
try {
    Path p=new Path("hdfs://test.server:9000/usr/test/test_file.txt");
    FileSystem fs = FileSystem.get(CONFIG);
    System.out.println(p.getName() + " exists: " + fs.exists(p));

    br=new BufferedReader(new InputStreamReader(fs.open(p)));
    String line = br.readLine();

    while (line != null) {
        System.out.println(line);
        line=br.readLine();
    }
}
finally {
    if(br != null) br.close();
}

此代码引发异常:
线程“main”org.apache.hadoop.hdfs.blockmissingexception中出现异常:无法获取块:bp-13917963-127.0.0.1-1398476189167:blk\u 1073741831\u 1007 file=/usr/test/test\u file.txt
谷歌给出了一些可能的建议,但都被证实了。数据节点已连接、处于活动状态并且具有足够的空间。hdfs dfsadmin–report的管理报告显示:
配置容量:52844687360(49.22 gb)
当前容量:48507940864(45.18 gb)
剩余dfs:48507887616(45.18 gb)
使用的dfs:53248(52 kb)
使用的dfs%:0.00%
复制块下:0
具有损坏副本的块:0
缺少块:0
可用数据节点:1(共1个,0个死亡)
实时数据节点:
名称:127.0.0.1:50010(test.server)
主机名:test.server
退役状态:正常
配置容量:52844687360(49.22 gb)
使用的dfs:53248(52 kb)
使用的非dfs:4336746496(4.04 gb)
剩余dfs:48507887616(45.18 gb)
使用的dfs%:0.00%
dfs剩余百分比:91.79%
配置的缓存容量:0(0 b)
使用的缓存:0(0 b)
剩余缓存:0(0 b)
缓存使用百分比:100.00%
缓存剩余百分比:0.00%
最后联系方式:2014年4月25日星期五22:16:56 pdt
客户端jar是直接从hadoop安装中复制的,因此没有版本不匹配。我可以用java类浏览文件系统并读取文件属性。我只是无法读取文件内容而不得到异常。如果我尝试用以下代码编写文件:

FileSystem fs = null;
BufferedWriter br = null;

System.setProperty("HADOOP_USER_NAME", "root");

try {
    fs = FileSystem.get(new Configuraion());

    //Path p = new Path(dir, file);
    Path p = new Path("hdfs://test.server:9000/usr/test/test.txt");
    br = new BufferedWriter(new OutputStreamWriter(fs.create(p,true)));
    br.write("Hello World");
}
finally {
    if(br != null) br.close();
    if(fs != null) fs.close();
}

这将创建文件,但不写入任何字节并引发异常:
线程“main”org.apache.hadoop.ipc.remoteexception(java.io.ioexception)中的异常:文件/usr/test/test.txt只能复制到0节点,而不是minreplication(=1)。此操作中有1个datanode正在运行,并且排除了1个节点。
在谷歌上搜索这一点表明可能存在空间问题,但从dfsadmin报告来看,似乎有足够的空间。这是一个普通的香草安装,我不能通过这个问题。
环境总结是:
服务器:
具有伪分布的hadoop 2.4.0(http://hadoop.apache.org/docs/r2.4.0/hadoop-project-dist/hadoop-common/singlecluster.html)
centos 6.5虚拟机64位服务器java 1.7.0_
客户:
windows 8(虚拟机)java 1.7.0\u 51
非常感谢您的帮助。

7d7tgy0s

7d7tgy0s1#

hadoop错误消息令人沮丧。他们往往不说自己的意思,与真正的问题无关。当客户机、namenode和datanode无法正常通信时,就会出现类似的问题。在你的情况下,我会从两个问题中选择一个:
您的集群在虚拟机中运行,其对客户端的虚拟化网络访问被阻止。
您使用的完全限定域名(fqdn)在客户端和主机之间的解析方式不一致。
主机名“test.server”非常可疑。检查以下各项:
test.server是fqdn吗?
这是您的conf文件中随处使用的名称吗?
客户机和所有主机是否可以正向和反向解析“test.server”及其ip地址并获得相同的结果?
是否在任何地方使用ip地址而不是fqdn?
“localhost”是否在任何地方使用?
必须删除fqdn、主机名、数字ip和本地主机使用中的任何不一致。永远不要在conf文件或客户机代码中混用它们。首选一致使用fqdn。数字ip的一致使用通常也有效。使用非限定主机名、localhost或127.0.0.1会导致问题。

xn1cxnb4

xn1cxnb42#

我们需要确保设置了fs.default.name space的配置,例如 configuration.set("fs.default.name","hdfs://ourHDFSNameNode:50000"); 下面是一段示例代码:

Configuration configuration = new Configuration();
 configuration.set("fs.default.name","hdfs://ourHDFSNameNode:50000");
 FileSystem fs = pt.getFileSystem(configuration);
 BufferedReader br = new BufferedReader(new InputStreamReader(fs.open(pt)));
 String line = null;
 line = br.readLine
 while (line != null) {
  try {
    line = br.readLine
    System.out.println(line);
  }
}
tmb3ates

tmb3ates3#

上面的答案指向正确的方向。请允许我补充以下内容:
namenode不直接读取或写入数据。
客户机(使用直接访问hdfs的java程序)与namenode交互以更新hdfs名称空间并检索块位置以进行读/写。
客户机直接与datanode交互以读取/写入数据。
您可以列出目录内容,因为 hostname:9000 你的客户端代码可以访问。你在做上面的数字2。
为了能够读写,您的客户机代码需要访问datanode(3号)。datanode dfs数据传输的默认端口是50010。有东西挡住了你和客户的联系 hostname:50010 . 可能是防火墙或ssh隧道配置问题。
我使用的是hadoop2.7.2,所以您可能有不同的端口号设置。

相关问题