无法连接到码头主机以外的码头容器

我有两个docker容器在Ubuntu上运行,其中一个是hadoop namenode,另一个是hadoop datanode。

现在我有我的Windows代码运行的Java代码使用Hadoop的FileSystem API复制文件从我的Windows文件系统远程码头hdfs。

import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.FileUtil; import org.apache.hadoop.fs.Path; import org.junit.Test; import java.io.File; public class HadoopTest { @Test public void testCopyFileToHDFS() throws Exception { Configuration configuration = new Configuration(); configuration.addResource(getClass().getClassLoader().getResourceAsStream("hadoop/core-site.xml")); configuration.addResource(getClass().getClassLoader().getResourceAsStream("hadoop/yarn-site.xml")); FileSystem fileSystem = FileSystem.get(configuration); FileUtil.copy(new File("c:\\windows-version.txt"),fileSystem, new Path("/testsa"), false,configuration); } } 

但我得到了以下错误:

 16:57:05.669 [Thread-4] DEBUG org.apache.hadoop.hdfs.DFSClient - Connecting to datanode 172.18.0.2:50010 16:57:15.654 [IPC Client (547201549) connection to /192.168.56.102:9000 from ignis] DEBUG org.apache.hadoop.ipc.Client - IPC Client (547201549) connection to /192.168.56.102:9000 from ignis: closed 16:57:15.655 [IPC Client (547201549) connection to /192.168.56.102:9000 from ignis] DEBUG org.apache.hadoop.ipc.Client - IPC Client (547201549) connection to /192.168.56.102:9000 from ignis: stopped, remaining connections 0 16:57:26.670 [Thread-4] INFO org.apache.hadoop.hdfs.DFSClient - Exception in createBlockOutputStream java.net.ConnectException: Connection timed out: no further information at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717) at org.apache.hadoop.net.SocketIOWithTimeout.connect(SocketIOWithTimeout.java:206) at org.apache.hadoop.net.NetUtils.connect(NetUtils.java:531) at org.apache.hadoop.hdfs.DFSOutputStream.createSocketForPipeline(DFSOutputStream.java:1533) at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.createBlockOutputStream(DFSOutputStream.java:1309) at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.nextBlockOutputStream(DFSOutputStream.java:1262) at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:448) 16:57:26.673 [Thread-4] INFO org.apache.hadoop.hdfs.DFSClient - Abandoning BP-53577818-172.18.0.2-1500882061263:blk_1073741827_1003 

您可以看到“连接到datanode 172.18.0.2:50010”的第一行错误是一个码头的内部IP地址。

我的Java代码运行在Docker主机之外的真正的Windows机器上。

我已经将Hadoop HDFS端口(例如9000和50010)映射到我的docker主机(ubuntu)。因此我可以通过docker主机ip地址和HDFS端口访问HDFS名称节点。

以下是我的java代码的逻辑:

1)Java代码正在运行在Windows机器上

2)Java代码使用FileSystem API将文件从Windows复制到远程HDFS。

3)客户端可以通过使用docker主机的ip地址和从docker container(例如9000)映射的端口连接到HDFS名称节点,

4)HDFS Namenode服务器将处理从客户端发送的请求,并将数据节点的IP地址返回给客户端。

5)客户端尝试使用数据节点的IP地址从本地复制文件

6)客户端得到错误,表示数据节点的IP地址不能访问,因为它是在码头容器内的IP地址

在这里输入图像描述

最后,我通过引入datanode的主机名来找到解决方案,并且在连接到datanode时启用hdfs客户端使用主机名而不是ip地址,我的客户端还需要将datanode主机名映射为docker主机ip地址,以下是详细步骤:

  1. 在docker-compose.xml中添加docker datanode容器的主机名

    主机名:datanode.company.com

  2. 启用hdfs(服务器和客户端)使用主机名而不是IP地址。

 <configuration> <property> <name>dfs.client.use.datanode.hostname</name> <value>true</value> </property> <property> <name>dfs.datanode.use.datanode.hostname</name> <value>true</value> </property> </configuration>