今天怀着忐忑的心情测试一下客户端上传文件,一开始创建文件夹成功,以为没什么问题了,但是接下来上传文件时,却发生了错误。😢 具体报错如下:

org.apache.hadoop.ipc.RemoteException(java.io.IOException): File /0529/dashen/test01.txt
 could only be written to 0 of the 1 minReplication nodes. There are 1 datanode(s) running and 1 node(s) are excluded in this operation.
	at org.apache.hadoop.hdfs.server.blockmanagement.BlockManager.chooseTarget4NewBlock(BlockManager.java:2312)
	at org.apache.hadoop.hdfs.server.namenode.FSDirWriteFileOp.chooseTargetForNewBlock(FSDirWriteFileOp.java:294)
	at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getAdditionalBlock(FSNamesystem.java:2939)
	at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.addBlock(NameNodeRpcServer.java:908)
	at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolServerSideTranslatorPB.addBlock(ClientNamenodeProtocolServerSideTranslatorPB.java:593)
	at org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$ClientNamenodeProtocol$2.callBlockingMethod(ClientNamenodeProtocolProtos.java)
	at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine2.java:532)
	at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:1070)
	at org.apache.hadoop.ipc.Server$RpcCall.run(Server.java:1020)
	at org.apache.hadoop.ipc.Server$RpcCall.run(Server.java:948)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:422)
	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1845)
	at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2952)


	at org.apache.hadoop.ipc.Client.getRpcResponse(Client.java:1562)
	at org.apache.hadoop.ipc.Client.call(Client.java:1508)
	at org.apache.hadoop.ipc.Client.call(Client.java:1405)
	at org.apache.hadoop.ipc.ProtobufRpcEngine2$Invoker.invoke(ProtobufRpcEngine2.java:234)
	at org.apache.hadoop.ipc.ProtobufRpcEngine2$Invoker.invoke(ProtobufRpcEngine2.java:119)
	at com.sun.proxy.$Proxy12.addBlock(Unknown Source)
	at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB.addBlock(ClientNamenodeProtocolTranslatorPB.java:530)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:422)
	at org.apache.hadoop.io.retry.RetryInvocationHandler$Call.invokeMethod(RetryInvocationHandler.java:165)
	at org.apache.hadoop.io.retry.RetryInvocationHandler$Call.invoke(RetryInvocationHandler.java:157)
	at org.apache.hadoop.io.retry.RetryInvocationHandler$Call.invokeOnce(RetryInvocationHandler.java:95)
	at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:359)
	at com.sun.proxy.$Proxy13.addBlock(Unknown Source)
	at org.apache.hadoop.hdfs.DFSOutputStream.addBlock(DFSOutputStream.java:1090)
	at org.apache.hadoop.hdfs.DataStreamer.locateFollowingBlock(DataStreamer.java:1867)
	at org.apache.hadoop.hdfs.DataStreamer.nextBlockOutputStream(DataStreamer.java:1669)
	at org.apache.hadoop.hdfs.DataStreamer.run(DataStreamer.java:715)

然后接下来我就在我的服务器里上传了一个文件试试,发现上传成功,没什么问题

hdfs上传过后找不到 hdfs上传文件失败_hadoop

为什么服务器里可以成功上传文件,而客户端却不行呢(客户端能上传文件,但是只有一个空壳,内部并没有数据)?但是客户端又可以成功创建文件夹目录呀!?

让我们智商300的大脑仔细思考一下,我们的文件目录,文件名是存放在哪里?而我们的具体数据又是写在哪里?

直接给出我们的分析结果

NameNode节点存放的是文件目录,也就是文件夹、文件名称,本地可以通过公网访问 NameNode,所以可以进行文件夹的创建,当上传文件需要写入数据到DataNode时,NameNode 和DataNode 是通过局域网进行通信,NameNode返回地址为 DataNode 的私有 IP,本地无法访问


解决方案

返回的IP地址无法返回公网IP,只能返回主机名,通过主机名与公网地址的映射便可以访问到DataNode节点,问题将解决。

由于代码的设置的优先级为最高,所以直接进行代码的设置。

Configuration conf = new Configuration();
conf.set("dfs.client.use.datanode.hostname", "true");//添加此配置信息即可
FileSystem fs = FileSystem.get(new URI("hdfs://host:9000"), conf, "root");

注意:

  1. 主机名我们可以通过下面的命令查看:

hadoop dfsadmin -report

  1. 本地还需要配置一下DNS域名映射,在C:\Windows\System32\drivers\etc的hosts文件中配置
  2. 阿里云等服务器还需要配置一下我们的安全组 9866
  3. 接下来就是我们的防火墙开放一下端口就行了



附:当然我们也可以直接在配置文件(项目下的配置文件和服务器配置文件都行)中进行一个简单配置:

<property>
    <name>dfs.client.use.datanode.hostname</name>
    <value>true</value>
    <description>only cofig in clients</description>
</property>



重新运行我们的代码应该就没什么问题了

hdfs上传过后找不到 hdfs上传文件失败_hadoop_02