使用JAVA API連接HDFS時我們需要使用NameNode的地址,開啟HA后,兩個NameNode可能會主備切換,如果連接的那臺主機NameNode掛掉了,連接就會失敗. HDFS提供了nameservices的方式進行訪問,這樣只要有一個NameNode活著,都可以正常訪問.
HDFS NameNode HA
在沒有HA的環境中,通常使用NameNode hostname訪問HDFS的URL.
hdfs://ochadoop111.jcloud.local:8020
為了保證HDFS服務的高可用,生產環境是必須要開啟NameNode HA的,此時應該用nameservices作為統一的logical name連接HDFS.
使用Ambari Enable NameNode HA之后,我的集群在ochadoop112.jcloud.local上增加了一個NameNode, HA相關的配置會自動產生.
首先在Ambari UI上查看custom hdfs-site配置. 注意端口號要配成rpc的端口號,而不能是http/https的.
dfs.nameservices=mycluster
dfs.namenode.rpc-address.mycluster.nn1=ochadoop111.jcloud.local:8020
dfs.namenode.rpc-address.mycluster.nn2=ochadoop112.jcloud.local:8020
dfs.ha.namenodes.mycluster=nn1,nn2
使用nameservices訪問HDFS的URL:
hdfs://mycluster:8020
JAVA API連接HDFS HA代碼如下:
Configuration conf=new Configuration(false);
String nameservices = "mycluster";
String[] namenodesAddr = {"ochadoop111.jcloud.local:8020","ochadoop112.jcloud.local:8020"};
String[] namenodes = {"nn1","nn2"};
conf.set("fs.defaultFS", "hdfs://" + nameservices);
conf.set("dfs.nameservices",nameservices);
conf.set("dfs.ha.namenodes." + nameservices, namenodes[0]+","+namenodes[1]);
conf.set("dfs.namenode.rpc-address." + nameservices + "." + namenodes[0], namenodesAddr[0]);
conf.set("dfs.namenode.rpc-address." + nameservices + "." + namenodes[1], namenodesAddr[1]);
conf.set("dfs.client.failover.proxy.provider." + nameservices,"org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");
String hdfsRPCUrl = "hdfs://" + nameservices + ":" + 8020;
DistributedFileSystem dfs = new DistributedFileSystem();
try {
dfs.initialize(URI.create(hdfsRPCUrl),conf);
Path tmpPath2 = new Path("/tmp2");
dfs.mkdir(tmpPath2,new FsPermission("777"));
FileStatus[] list = dfs.listStatus(new Path("/"));
for (FileStatus file : list) {
System.out.println(file.getPath());
}
dfs.setQuota(tmpPath2,100,1000);
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
dfs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
WebHDFS
通過WebHDFS訪問HA集群時,就沒有rpc方式那么方便了,有四種解決方法,我覺得第4個方法最簡單, YARN的ResourceManager HA我就是按這個思路處理的.
- 使用httpfs,這個是CDH的產品,需要額外安裝
- 使用knox安全網關,這樣訪問的接口就都被knox統一了
- 每次訪問之前都從zookeeper中拿當前Active NameNode的地址
- 每次訪問輪詢兩個namenode
YARN ResourceManager HA
ResourceManager HA存在與NameNode HA類似的問題,能否通過統一的logical name訪問RM的REST API呢? 答案是暫時不支持.
目前YARN只能支持standy RM把請求重定向到Active RM上. 也就是說假如主備RM都活著,當客戶端向standby RM發HTTP請求時,standby RM會重定向到active RM上,但是如果standby RM不幸掛掉了,而Active RM還正常工作,此時請求就會失敗.
解決方法其實也很簡單,就是在調用RM REST API時輪詢兩個RM.