感谢原文作者 vaf714 做出的解答!
原文链接:https://blog.csdn.net/vaf714/article/details/82996860
前提
-
A 云主机是 Linux 环境,搭建 Hadoop 伪分布式,公网 IP:49.4.71.xxx,内网 IP:192.168.0.80,主机名:ruixin4。
-
Hadoop 配置信息如下:
<property> <name>fs.defaultFS</name> <value>hdfs://ruixin4:8020</value> </property>
-
/etc/hosts 文件配置:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.0.80 ruixin4
症状
-
在 A 云主机上开启 HDFS,JPS 查看进程都没有异常,通过 Shell 操作 HDFS 文件也没有问题。
-
通过浏览器访问 50070 端口管理界面也没有问题。
-
在本地机器上使用 Java API 操作远程 HDFS 文件,URI 使用公网 IP,代码如下:
fileSystem = FileSystem.get(new URI("hdfs://49.4.71.9:8020"), configuration, "hadoop");
-
可以正常创建文件夹
-
可以正常创建文件
-
往创建完文件返回的输出流中写入内容是报如下异常
File xxx could only be replicated to 0 nodes instead of minReplication (=1).
-
分析
- 本地 Shell 可以正常操作,排除集群搭建和进程没有启动的问题。
- 我在另一台云主机(B 云主机)中搭建了开发环境,B 主机和 A 主机在同一内网,在 B 中可以正常操作,基本确定了是由于内外网的原因。
- 查阅资料发现 HDFS 中的文件夹和文件名都是存放在 NameNode 上,操作不需要和 DataNode 通信,因此可以正常创建文件夹和创建文件说明本地和远程 NameNode 通信没有问题。
- 那么很可能是本地和远程 DataNode 通信有问题。
猜测
文件夹和文件名都是存放在 NameNode 上的,我本地可以通过公网访问 NameNode,所以创建文件夹和文件都可以,但是当我写数据的时候,NameNode 和DataNode 是通过内网通信的,NameNode 会返回给我 DataNode 的内网 IP,我本地就访问不了了。
还有一种可能,云服务器没有开放 DataNode 用于数据传输服务端口 默认是 50010。
验证
想办法使本地可以访问到 DataNode。
-
添加一句配置,使 NameNode 返回 DataNode 的主机名而不是 IP:
configuration.set("dfs.client.use.datanode.hostname", "true");
另外也可以配置 hdfs-site.xml 文件内容如下:
<property> <name>dfs.client.use.datanode.hostname</name> <value>true</value> </property>
-
本地可以拿到了 DataNode 的主机名,要访问还需要配置本地 Hosts 映射:
49.4.71.xxx ruixin4
windows 下 hosts 文件地址:C:\Windows\System32\drivers\etc\hosts
-
云服务器打开 50010 端口
-
结果正常访问