从java写入hdfs,获取“只能复制到0个节点,而不是minreplication”

zd287kbt  于 2021-06-04  发布在  Hadoop
关注(0)|答案(11)|浏览(393)

我已经下载并启动了cloudera针对cdh4的hadoop演示vm(运行Hadoop2.0.0)。我正在尝试编写一个java程序,它将从我的Windows7机器(运行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文件只定义了on属性: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)

我环顾了一下internet,发现磁盘空间不足时会发生这种情况,但在运行“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)上的权限,但没有解决问题(我甚至给了所有人完全访问权限)。
我注意到,当我通过hueweb应用程序浏览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用户)。但这给了我同样的错误。

dnph8jn4

dnph8jn41#

我有一个类似的问题,在我的情况下,我只是清空以下文件夹 ${hadoop.tmp.dir}/nm-local-dir/usercache/{{hdfs_user}}/appcache/

q3qa4bjr

q3qa4bjr2#

我遇到了类似的问题,有两条信息可能对你有所帮助。
我意识到的第一件事是我使用ssh tunnel来访问name节点,当客户机代码试图访问数据节点时,它找不到数据节点,因为隧道以某种方式破坏了通信。然后我在hadoop name节点所在的同一个框中运行客户机,它解决了问题。总之,非标准的网络配置混淆了hadoop查找数据节点的能力。
我使用ssh tunnel的原因是我不能远程访问name节点,我认为这是由于admin的端口限制,所以我使用ssh tunnel来绕过限制。但事实证明这是对hadoop的错误配置。
在core-site.xml中

<name>fs.defaultFS</name>
<value>hdfs://localhost:9000</value>

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

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

gijlo24d

gijlo24d3#

在中添加给定属性 hdfs-site.xml ```

dfs.replication
1

并将此文件也添加到程序中

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

停止hadoop

stop-all.sh

那就开始吧

start-all.sh

kuuvgm7e

kuuvgm7e4#

我也有同样的问题。
在我的例子中,问题的关键是跟踪错误消息。
此操作中有1个datanode正在运行,并且排除了1个节点。
这意味着您的hdfs客户端无法使用50010端口连接到您的datanode。当您连接到hdfs namenode时,您可以获得datanode的状态。但是,hdfs客户端将无法连接到datanode。
(在hdfs中,namenode管理文件目录和数据节点。如果hdfs客户机连接到namnenode,它将找到包含数据的datanode的目标文件路径和地址。然后hdfs客户机将与datanode通信(您可以使用netstat检查这些datanode uri。因为,hdfs客户机将尝试使用namenode通知的by address与datanodes通信)
我通过以下方法解决了这个问题:
正在防火墙中打开50010(dfs.datanode.address)端口。
添加属性 "dfs.client.use.datanode.hostname", "true" 将主机名添加到我的客户端pc中的hostfile。
很抱歉我的英语水平很差。

efzxgjgh

efzxgjgh5#

下面是如何在hdfs中创建文件:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

FileSystem hdfs = FileSystem.get(context.getConfiguration());
Path outFile=new Path("/path to store the output file");

String line1=null;

if (!hdfs.exists(outFile)){
            OutputStream out = hdfs.create(outFile);
            BufferedWriter br = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
            br.write("whatever data"+"\n");
            br.close();
            hdfs.close();
        }
else{
            String line2=null;
            BufferedReader br1 = new BufferedReader(new InputStreamReader(hdfs.open(outFile)));
            while((line2=br1.readLine())!=null){
                line1=line1.concat(line2)+"\n";
            }
            br1.close();
            hdfs.delete(outFile, true);
            OutputStream out = hdfs.create(outFile);
            BufferedWriter br2 = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
            br2.write(line1+"new data"+"\n");
            br2.close();
            hdfs.close();
        }
dldeef67

dldeef676#

转到LinuxVM并检查主机名和ip地址(使用ifconfig cmd)。然后在linux vm中编辑/etc/host文件
IP地址(spalce)主机名
示例:192.168.110.27 clouderavm
并更改所有hadoop配置文件
core-site.xml文件
hdfs-site.xml文件
mapred-site.xml文件
yarn-site.xml文件
将localhost或localhost.localdomain或0.0.0.0更改为主机名
然后重新启动cloudera管理器。
在windows计算机中,编辑c:\windows\system32\drivers\etc\hosts
在末尾添加一行
您可以使用虚拟机ip和主机名(与您在虚拟机中的/etc/host文件上所做的相同)
VMIP地址vmhostname
例子:
192.168.110.27云虚拟机
然后检查现在,它应该工作,为细节配置检查以下视频从你管
https://www.youtube.com/watch?v=fsgpyhjgiry

vxqlmq5t

vxqlmq5t7#

这似乎是fs的一些问题。cross-site.xml中的参数与其试图读取的文件不匹配
或者
路径中有一些常见的不匹配(我看到有一个windows引用)。
您可以使用cygwin工具来设置路径,并将其放置在datanodes和temp文件位置的位置,这应该足以完成技巧位置:$/bin/cygpath.exe
p、 在我看来,复制似乎不是这里的主要问题

qq24tv8q

qq24tv8q8#

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

h9a6wy2h

h9a6wy2h9#

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

dsekswqp

dsekswqp10#

因为我在寻找完全相同的问题的过程中发现了许多类似的问题,我想我会分享最终对我有用的东西。我在hortonworks上找到了这个论坛帖子:https://community.hortonworks.com/questions/16837/cannot-copy-from-local-machine-to-vm-datanode-via.html
答案是真正理解调用new 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());
}
jjjwad0x

jjjwad0x11#

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

相关问题