使用hdfs:// URI时NameNode HA

lyo*_*omi 8 hadoop uri high-availability hdfs

使用HDFS或HFTP URI方案(例如hdfs://namenode/path/to/file),我可以访问HDFS集群而无需其XML配置文件.运行shell命令就像当它是非常方便的hdfs dfs -get,hadoop distcp或者像星火读取文件sc.hadoopFile(),因为我没有为所有相关的HDFS集群,那些代码可能会运行的所有节点复制和管理XML文件.

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

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

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

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

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

mrs*_*vas 5

在这种情况下,我们不应该检查活动名称节点主机和端口组合,而是应该使用名称服务,因为名称服务会自动将客户端请求传输到活动名称节点

名称服务就像 Namenode 之间的代理一样,总是将 HDFS 请求转移到活动的 namenode

例子: 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>
Run Code Online (Sandbox Code Playgroud)

现在指定名称节点 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>
Run Code Online (Sandbox Code Playgroud)

然后将namenode id与namenode主机链接

dfs.namenode.rpc-address.[$nameservice ID].[$namenode 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>
Run Code Online (Sandbox Code Playgroud)

使用Nameservice正确配置Namenode HA涉及很多属性

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

hdfs://mycluster/file/location/in/hdfs/wo/namenode/host
Run Code Online (Sandbox Code Playgroud)

编辑:

使用 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 ...
Run Code Online (Sandbox Code Playgroud)