本地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