使用hdfs:// URI时NameNode HA

时间:2015-04-14 18:01:55

标签: hadoop uri hdfs high-availability

使用HDFS或HFTP URI方案(例如hdfs://namenode/path/to/file),我可以访问HDFS群集而无需其XML配置文件。运行像hdfs dfs -gethadoop distcp这样的shell命令或者像sc.hadoopFile()那样从Spark读取文件时非常方便,因为我不必复制和管理所有相关HDFS的xml文件集群到那些代码可能运行的所有节点。

这种方法的一个缺点是我必须使用活动的NameNode主机名,否则Hadoop会抛出一个抱怨NN处于待机状态的异常。

通常的解决方法是尝试一个,然后尝试另一个,如果发现任何异常,或直接连接到ZooKeeper并使用protobuf解析二进制数据。

与(例如)mysql's loadbalance URIZooKeeper's connection string相比,这两种方法都很麻烦,我可以用逗号分隔URI中的所有主机,驱动程序会自动找到要与之通信的节点

假设我有活动和备用的namenode主机nn1nn2。引用HDFS特定路径的最简单方法是:

  • 可用于hdfshadoop
  • 等命令行工具
  • 可以在Hadoop Java API中使用(因此像Spark一样依赖于它的工具),配置最少
  • 无论当前哪个namenode处于活动状态,
  • 都能正常工作。

1 个答案:

答案 0 :(得分:4)

  

在这个场景中,我们应该使用 nameservice ,而不是检查有效的namenode主机和端口组合, nameservice会自动将客户端请求转移到活动的namenode

     

名称服务就像Namenodes中的代理一样,它总是将HDFS请求转移到活动的名称节点

示例: hdfs://nameservice_id/file/path/in/hdfs

创建nameservice

的示例步骤

hdfs-site.xml 文件

通过向其添加ID来创建名称服务(此处nameservice_id为 mycluster

<property>
  <name>dfs.nameservices</name>
  <value>mycluster</value>
  <description>Logical name for this new nameservice</description>
</property>

现在指定namenode id来确定集群中的名称节点

dfs.ha.namenodes。[$ nameservice ID]

<property>
  <name>dfs.ha.namenodes.mycluster</name>
  <value>nn1,nn2</value>
  <description>Unique identifiers for each NameNode in the nameservice</description>
</property>

然后将namenode id与namenode主机链接

dfs.namenode.rpc-address。[$ nameservice ID]。[$ name node ID]

<property>
  <name>dfs.namenode.rpc-address.mycluster.nn1</name>
  <value>machine1.example.com:8020</value>
</property>
<property>
  <name>dfs.namenode.rpc-address.mycluster.nn2</name>
  <value>machine2.example.com:8020</value>
</property>

Configure Namenode HA properly with Nameservice

涉及的属性太多了
  

通过此设置,文件的HDFS URL将如下所示

hdfs://mycluster/file/location/in/hdfs/wo/namenode/host

编辑:

使用java代码应用属性

Configuration conf = new Configuration(false);
conf.set("dfs.nameservices","mycluster");
conf.set("dfs.ha.namenodes.mycluster","nn1,nn2");
conf.set("dfs.namenode.rpc-address.mycluster.nn1","machine1.example.com:8020");
conf.set("dfs.namenode.rpc-address.mycluster.nn2","machine2.example.com:8020");

FileSystem fsObj =  FileSystem.get("relative/path/of/file/or/dir", conf);

// now use fsObj to perform HDFS shell like operations
fsObj ...