本地IDEA访问ECS服务器HDFS

原本是配置了阿里云ECS服务器,但是用终端vim修改调试代码,总是会不方便。
后面想到有两种解决办法:

  • 用本地IDEA调试代码,然后直接连接服务器的HDFS等端口,直接调试
  • 用本地IDEA调试代码,然后打包,发到服务器上进行运行

下面是IDEA访问服务器hadoop的一个测试,以及遇到的问题和解决方法。

Maven添加Hadoop依赖

通过调查,没有使用MapReduce的话,只要添加hadoop-common,hadoop-client和hadoop-hdfs这三个。由于我服务器上的Hadoop是3.1.3版本的,Maven依赖如下:
大家可以到这个网址找需要的Jar包的Maven依赖
https://mvnrepository.com/tags/hadoop

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>3.1.3</version>
        </dependency>
    </dependencies>

这里没有添加hadoop-core,版本最新是1.2.1,这是因为Hadoop2.x后就没有使用这个包了,而是以其他一些依赖包来代替其功能。

依赖下载失败

如果有报java.lang.NoClassDefFoundError: com/ctc/wstx/io/InputBootstrapper是依赖包不全的原因,需要更换仓库下载依赖包。

使用IDEA下载这些依赖,一直是红色,没下载下来。后面通过添加别的仓库来解决这个问题,在pom.xml上添加以下字段:

<repositories>
    <repository>
        <id>alimaven</id>
        <name>Maven Aliyun Mirror</name>
        <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

如果有使用到MapReduce

通过调查,如果使用了MapReduce,要添加以下依赖:

<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-mapreduce-client-core</artifactId>
    <version>3.1.3</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-mapreduce-client-common</artifactId>
    <version>3.1.3</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-mapreduce-client-jobclient</artifactId>
    <version>3.1.3</version>
</dependency>

如果有使用到Yarn

<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-yarn-api -->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-yarn-api</artifactId>
    <version>3.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-yarn-common -->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-yarn-common</artifactId>
    <version>3.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-yarn-client -->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-yarn-client</artifactId>
    <version>3.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-yarn-server-common -->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-yarn-server-common</artifactId>
    <version>3.1.3</version>
</dependency>

查看HDFS上是否存在test.txt文件

需要修改hadoop的core-site.xml

在hadoop/etc/hadoop/下有一个core-site.xml文件。这里我原本设置的是localhost:9000,本地单机。但这就造成了我访问失败。出现以下错误信息。

java.net.ConnectException: Call From xxx to 公网ip:9000 failed on connection exception: java.net.ConnectException: Connection refused

这里是连接不上,就很奇怪。调查后,发现需要修改core.site文件。

将hdfs://localhost:9000改为hdfs://内网ip:9000
或者
将hdfs://localhost:9000改为hdfs://0.0.0.0:9000

https://blog.csdn.net/k393393/article/details/91869501

0.0.0.0表示当前局域网的所有地址。这里修改后,访问成功,自己也产生了一个疑问。在随笔最后面,希望您能看一下。

代码

这里的filename是文件所在路径及文件名,fs.defaultFS设置的是服务器ip:端口。运行即可访问。

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

public class fileexist {
    public static void main(String[] args) {
        try {
            String filename = "/user/hadoop/test.txt";

            Configuration conf = new Configuration();
            //这里xxx.xxx.xxx.xxx是公网ip
            conf.set("fs.defaultFS","hdfs://xxx.xxx.xxx.xxx:9000");
            conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");
            FileSystem fs = FileSystem.get(conf);
            if(fs.exists(new Path(filename))){
                System.out.println("文件存在");
            }else{
                System.out.println("文件不存在");
            }
            fs.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

关于阿里云公网、私网、端口的一个问题

欢迎您指教,指出我不对的地方或者没有考虑到的地方。

问题

我在IDEA访问的是公网IP:端口,也就是访问阿里云给我面向外部的网络。而我却通过公网IP:端口访问到了私网IP:端口。

这里我就疑惑了,因为我没有在阿里云设置公网IP和私网IP之间的端口映射。我理解私网为公网的一个局域网,通过NAT协议(这里可能理解错误)。可以通过公网IP访问私网IP,但是为什么公网IP:9000就是私网IP的9000端口呢?

如果这个局域网中有多个IP,那岂不是会造成端口冲突?我是觉得应该是有一个设置,来修改公网IP端口和私网IP端口的映射。或者说这个局域网就一个私网IP,就不会有端口冲突,那这又造成了IP地址的浪费,越想越觉得自己网络学的差劲,需要重新翻书了。

我在调查中发现了以下几篇文章,但没能很好解决自己的疑问。
https://blog.csdn.net/wangxiaai/article/details/104885013
https://ask.csdn.net/questions/1058767?sort=id

关于对HDFS的数据读写

这里我们只是查看是否存在文件test.txt,这样的操作,我们只是对NameNode进行访问,即访问HDFS文件系统的目录树。而在后面,数据读写的时候,是需要对DataNode进行访问。而HDFS这里有一个需要注意的是,NameNode返回给客户端的DataNode是地址IP的形式,在阿里云这里,返回的是内网,所以会一直访问不了DataNode,造成读写失败。所以在对API操作中发现需要添加一个小设置。设置NameNode返回给客户端的DataNode是主机名,让客户端自己解析成IP地址。

conf.set("dfs.client.use.datanode.hostname", "true");
//或者在hdfs-site.xml设置这个属性为true
posted @ 2020-07-05 10:57  Tanglement  阅读(591)  评论(1编辑  收藏  举报