从Java写入HDFS,获取"只能复制到0个节点而不是minReplication"

时间:2013-01-11 23:43:15

标签: java hadoop hdfs

我已经下载并启动了Cloudera用于CDH4的Hadoop演示VM(运行Hadoop 2.0.0)。我正在尝试编写一个将从我的Windows 7机器运行的Java程序(与运行VM的机器/操作系统相同)。我有一个示例程序,如:

public static void main(String[] args) {
    try{
        Configuration conf = new Configuration();
        conf.addResource("config.xml");
        FileSystem fs = FileSystem.get(conf);
        FSDataOutputStream fdos=fs.create(new Path("/testing/file01.txt"), true);
        fdos.writeBytes("Test text for the txt file");
        fdos.flush();
        fdos.close();
        fs.close();
    }catch(Exception e){
        e.printStackTrace();
    }

}

我的config.xml文件只定义了属性:fs.default.name = hdfs:// CDH4_IP:8020。

当我运行它时,我遇到以下异常:

org.apache.hadoop.ipc.RemoteException(java.io.IOException): File /testing/file01.txt could only be replicated to 0 nodes instead of minReplication (=1).  There are 1 datanode(s) running and 1 node(s) are excluded in this operation.
    at org.apache.hadoop.hdfs.server.blockmanagement.BlockManager.chooseTarget(BlockManager.java:1322)
    at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getAdditionalBlock(FSNamesystem.java:2170)
    at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.addBlock(NameNodeRpcServer.java:471)
    at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolServerSideTranslatorPB.addBlock(ClientNamenodeProtocolServerSideTranslatorPB.java:297)
    at org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$ClientNamenodeProtocol$2.callBlockingMethod(ClientNamenodeProtocolProtos.java:44080)
    at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:453)
    at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:898)
    at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:1693)
    at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:1689)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:396)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1332)
    at org.apache.hadoop.ipc.Server$Handler.run(Server.java:1687)
    at org.apache.hadoop.ipc.Client.call(Client.java:1160)
    at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:202)
    at $Proxy9.addBlock(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:164)
    at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:83)
    at $Proxy9.addBlock(Unknown Source)
    at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB.addBlock(ClientNamenodeProtocolTranslatorPB.java:290)
    at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.locateFollowingBlock(DFSOutputStream.java:1150)
    at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.nextBlockOutputStream(DFSOutputStream.java:1003)
    at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:463)

我环顾了互联网,似乎当磁盘空间不足时就会发生这种情况但是当我运行“hdfs dfsadmin -report”时,情况就不是这样了我得到以下内容:

Configured Capacity: 25197727744 (23.47 GB)
Present Capacity: 21771988992 (20.28 GB)
DFS Remaining: 21770715136 (20.28 GB)
DFS Used: 1273856 (1.21 MB)
DFS Used%: 0.01%
Under replicated blocks: 0
Blocks with corrupt replicas: 0
Missing blocks: 0

-------------------------------------------------
Datanodes available: 1 (1 total, 0 dead)

Live datanodes:
Name: 127.0.0.1:50010 (localhost.localdomain)
Hostname: localhost.localdomain
Decommission Status : Normal
Configured Capacity: 25197727744 (23.47 GB)
DFS Used: 1273856 (1.21 MB)
Non DFS Used: 3425738752 (3.19 GB)
DFS Remaining: 21770715136 (20.28 GB)
DFS Used%: 0.01%
DFS Remaining%: 86.4%
Last contact: Fri Jan 11 17:30:56 EST 201323 EST 2013

我也可以在VM中运行此代码。我不确定问题是什么或如何解决它。这是我第一次使用hadoop,所以我可能会遗漏一些基本的东西。有什么想法吗?

更新

我在日志中看到的唯一一个异常类似于客户端上的get异常:

java.io.IOException: File /testing/file01.txt could only be replicated to 0 nodes instead of minReplication (=1).  There are 1 datanode(s) running and 1 node(s) are excluded in this operation.
    at org.apache.hadoop.hdfs.server.blockmanagement.BlockManager.chooseTarget(BlockManager.java:1322)
    at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getAdditionalBlock(FSNamesystem.java:2170)
    at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.addBlock(NameNodeRpcServer.java:471)
    at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolServerSideTranslatorPB.addBlock(ClientNamenodeProtocolServerSideTranslatorPB.java:297)
    at org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$ClientNamenodeProtocol$2.callBlockingMethod(ClientNamenodeProtocolProtos.java:44080)
    at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:453)
    at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:898)
    at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:1693)
    at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:1689)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:396)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1332)
    at org.apache.hadoop.ipc.Server$Handler.run(Server.java:1687)

我尝试更改数据目录(/ var / lib / hadoop-hdfs / cache / hdfs / dfs / data)的权限,并且没有修复它(我甚至提供了对所有人的完全访问权限)。

我注意到当我通过HUE Web应用程序浏览HDFS时,我看到文件夹结构已创建,文件确实存在,但它是空的。我尝试使用

将文件放在默认用户目录下
FSDataOutputStream fdos=fs.create(new Path("testing/file04.txt"), true); 

而不是

FSDataOutputStream fdos=fs.create(new Path("/testing/file04.txt"), true);

这使文件路径变为“/user/dharris/testing/file04.txt”('dharris'是我的Windows用户)。但这给了我同样的错误。

11 个答案:

答案 0 :(得分:11)

我遇到了同样的问题 在我的情况下,问题的关键是跟随错误消息 在此操作中,有1个数据节点正在运行,1个节点被排除在外。

这意味着您的hdfs-client无法使用50010端口连接到您的datanode。 当您连接到hdfs namenode时,您可以获得datanode的状态。但是,您的hdfs-client无法连接到您的datanode。

(在hdfs中,namenode管理文件目录和datanode。如果hdfs-client连接到namnenode,它将找到目标文件路径和具有数据的datanode地址。然后hdfs-client将与datanode通信。 (您可以使用netstat检查那些datanode uri。因为,hdfs-client将尝试使用namenode通知的地址与datanode进行通信)

解决了这个问题:

  1. 在防火墙中打开50010(dfs.datanode.address)端口。
  2. 添加属性"dfs.client.use.datanode.hostname", "true"
  3. 在我的客户端PC中将主机名添加到主机文件。
  4. 对不起我的英语能力差。

答案 1 :(得分:3)

转到linux VM并检查主机名和iP ADDRESS(使用ifconfig cmd)。 然后在linux vm中使用

编辑/ etc / host文件

IPADDRESS(SPALCE)主机名

示例: 192.168.110.27 clouderavm

并更改所有hadoop配置文件,如

芯-site.xml中

HDFS-site.xml中

mapred-site.xml中

纱-site.xml中

localhost或localhost.localdomain或0.0.0.0 更改为您的主机名

然后重启cloudera manger。

在Windows机器中

编辑 C:\ Windows \ System32 \ Drivers \ etc \ hosts

最后用

添加一行

你是vm机器的ip和主机名(与在vm中的/ etc / host文件上完成的相同)

VMIPADRESS VMHOSTNAME

示例:

192.168.110.27 clouderavm

然后立即检查,它应该可以工作,从你管的视频后面的详细配置检查

https://www.youtube.com/watch?v=fSGpYHjGIRY

答案 2 :(得分:2)

hdfs-site.xml

中添加指定属性
<property>
   <name>dfs.replication</name>
   <value>1</value>
 </property>

并在程序中添加此文件

conf.addResource("hdfs-site.xml");

停止hadoop

stop-all.sh

然后开始

start-all.sh

答案 3 :(得分:1)

我遇到了类似的问题,有两条信息可能对你有所帮助。

  1. 我意识到的第一件事是我使用ssh隧道来访问名称节点,当客户端代码尝试访问数据节点时,由于隧道以某种方式搞砸了通信,它无法找到数据节点。然后我在与hadoop名称节点相同的框上运行客户端,它解决了问题。简而言之,非标准网络配置混淆hadoop来查找数据节点。

  2. 我使用ssh隧道的原因是我无法远程访问名称节点,我认为这是由于admin的端口限制,所以我使用ssh隧道来绕过限制。但事实证明这是对hadoop的错误配置。

  3. 在我更改

    后的core-site.xml中
    <name>fs.defaultFS</name>
    <value>hdfs://localhost:9000</value>
    

    <value>hdfs://host_name:9000</value>
    

    我不再需要ssh turnnel,我可以远程访问hdfs。

答案 4 :(得分:1)

由于我在寻找完全相同的问题时发现了很多像这样的问题,我想我会分享最终对我有用的东西。我在Hortonworks上发现了这个论坛帖子:https://community.hortonworks.com/questions/16837/cannot-copy-from-local-machine-to-vm-datanode-via.html

答案是真正了解调用新Configuration()的含义并根据需要设置正确的参数。就我而言,这正是该帖中提到的那个。所以我的工作代码看起来像这样。

try {
    Configuration config = new Configuration();
    config.set("dfs.client.use.datanode.hostname", "true");
    Path pdFile = new Path("stgicp-" + pd);
    FileSystem dFS = FileSystem.get(new URI("hdfs://" + HadoopProperties.HIVE_HOST + ":" + HadoopProperties.HDFS_DEFAULT_PORT), config, 
            HadoopProperties.HIVE_DEFAULT_USER);
    if (dFS.exists(pdFile)) {
        dFS.delete(pdFile, false);
    } 
    FSDataOutputStream outStream = dFS.create(pdFile);
    for (String sjWLR : processWLR.get(pd)) {
        outStream.writeBytes(sjWLR);
    }     
    outStream.flush();
    outStream.close();

    dFS.delete(pdFile, false);
    dFS.close();
} catch (IOException | URISyntaxException | InterruptedException e) {
    log.error("WLR file processing error: " + e.getMessage());
}

答案 5 :(得分:0)

在hadoop配置中,默认复制设置为3.检查一次并根据您的要求进行更改

答案 6 :(得分:0)

您可以尝试手动删除数据(dfs / data)文件夹并格式化namenode。然后你可以开始hadoop。

答案 7 :(得分:0)

从错误信息复制因素似乎很好,即。 似乎datanode正常运行或有权限问题。 检查权限并检查用户的datanode状态,您正在尝试运行hadoop。

答案 8 :(得分:0)

我遇到了类似的问题,在我的情况下,我刚刚清空了以下文件夹${hadoop.tmp.dir}/nm-local-dir/usercache/{{hdfs_user}}/appcache/

答案 9 :(得分:0)

这似乎是FS的一些问题。 cross-site.xml中的参数与它尝试读取的文件不匹配

OR

路径中存在一些常见的不匹配(我看到有一个WINDOWS参考)。

您可以使用cygwin工具设置路径并将其放置在数据节点和临时文件位置的位置,这应该足以完成 位置:$ / bin / cygpath.exe

  

P.S。根据我的说法,复制似乎不是主要问题

答案 10 :(得分:0)

以下是我在HDFS中创建文件的方法:

$(window).load(function() { 
    alert("window load occurred!");
});