Hadoop学习笔记1 - 使用Java API访问远程hdfs集群

时间:2023-09-11 20:35:26

转载请标注原链接 http://www.cnblogs.com/xczyd/p/8570437.html

2018年3月从新司重新起航了。之前在某司过了的蛋疼三个月,也算给自己放了个小假了。

第一个小目标,从腾讯云上的hdfs集群拷贝一些文件到本地。唔唔,听上去似乎很简单的样子。

于是新建了一个Java的Maven工程,在pom.xml中添加如下依赖:

<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.0</version>
</dependency>

由于腾讯云上的集群是hdfs-2.6.0版本,所以我们的客户端也用2.6.0,尽量保持一致。

不过2.6.0可不是一个好版本,因为它与任何已知的HBase版本都不能做到兼容|||- -

HBase与Hadoop的兼容性详情见http://hbase.apache.org/book.html#configuration

然后,简单百度了一下访问hdfs的Java API的写法,于是得到了下面的代码:

// 根据给定的URI和用户名,访问hdfs的配置参数
Configuration conf = new Configuration(); // 允许访问datanode时使用域名,默认使用IP
conf.set("dfs.client.use.datanode.hostname","true"); // Hadoop的用户名,应当与远端启动hdfs进程的用户名相同,或者根据hdfs的安全设置自行配置
String hdfsUserName = "root"; URI hdfsUri = null;
try {
// NameNode的访问路径
hdfsUri = new URI("hdfs://hd-nn-test-01:9000");
} catch (URISyntaxException e) {
e.printStackTrace();
} try {
// 创建FileSystem对象,并调用copyToLocalFile函数将hdfs中的一个文件拷贝到本地目录
FileSystem fs = FileSystem.get(hdfsUri, conf, hdfsUserName);
fs.copyToLocalFile(new Path("/tmp/test.txt"),
new Path("/tmp"));
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}

其中加粗的那一行配置是使用外网IP访问一个同时具有内外网IP的hdfs集群时,所需要的一个特定配置。

需要添加这个配置的原因在于,客户端访问hdfs的namenode之后,获得的datanode信息全是云平台内网的IP。

如果直接用这个内网IP去访问,是无法得到hdfs的文件的。

https://hadoop.apache.org/docs/r2.8.0/hadoop-project-dist/hadoop-hdfs/HdfsMultihoming.html

这个链接中有一节专门介绍了这个问题的产生原因及解决办法。

添加这个配置的同时,还需要修改客户端的hosts文件,将云上的hdfs集群的域名与外网IP做一下映射。

这个配置在hdfs-2.6.0及以后的版本中是有效的,但是更往前的版本是否有效,还没来得及做进一步测试。

PS:其实这个坑困扰了我差不多一整天,一开始试图用SSH Tunnel来解决这个问题,未果;

又想用端口转发,也没有成功;后来想尝试nginx做反向代理,还没来得及尝试就偶然间发现了这个配置,

于是用了比较优雅的一个方式解决了此问题。