生產環境 Hadoop 採用 **NameNode HA (High Availability)** 架構,Java 客戶端需正確配置 `dfs.ha.namenodes`、`failover proxy` 才能自動切換 Active/Standby NameNode。同時提交 MapReduce Job 需設定 YARN ResourceManager 與 HDFS 相關參數。
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class HdfsHaClient {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
// --- 核心 HA 配置 ---
conf.set("fs.defaultFS", "hdfs://mycluster"); // 邏輯名稱
conf.set("dfs.nameservices", "mycluster"); // 服務名
conf.set("dfs.ha.namenodes.mycluster", "nn1,nn2"); // 兩個 NameNode ID
conf.set("dfs.namenode.rpc-address.mycluster.nn1", "nn1-host:8020");
conf.set("dfs.namenode.rpc-address.mycluster.nn2", "nn2-host:8020");
// 自動故障轉移代理
conf.set("dfs.client.failover.proxy.provider.mycluster",
"org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");
// 可選:超時與重試
conf.setInt("ipc.client.connect.timeout", 5000);
conf.setInt("ipc.client.connect.max.retries", 3);
try (FileSystem fs = FileSystem.get(conf)) {
FileStatus[] statuses = fs.listStatus(new Path("/"));
for (FileStatus status : statuses) {
System.out.println(status.getPath().getName() + "\t" +
(status.isDirectory() ? "DIR" : "FILE") + "\t" + status.getLen());
}
}
}
}
使用 `RunJar` 模擬 `hadoop jar` 指令,將配置透過 `-D` 參數傳入。
public class SubmitMrJob {
public static void main(String[] args) throws Exception {
String[] params = new String[] {
// 1. Jar 包路徑 (含 WordCount 範例)
"/opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar",
"wordcount", // 主類別名稱 (範例類)
// 2. YARN ResourceManager
"-D", "yarn.resourcemanager.address=rm-host:8032",
"-D", "yarn.resourcemanager.scheduler.address=rm-host:8030",
// 3. HDFS HA (同檔案系統配置)
"-D", "fs.defaultFS=hdfs://mycluster/",
"-D", "dfs.nameservices=mycluster",
"-D", "dfs.ha.namenodes.mycluster=nn1,nn2",
"-D", "dfs.namenode.rpc-address.mycluster.nn1=nn1-host:8020",
"-D", "dfs.namenode.rpc-address.mycluster.nn2=nn2-host:8020",
"-D", "dfs.client.failover.proxy.provider.mycluster=org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider",
// 4. 執行引擎
"-D", "mapreduce.framework.name=yarn",
"-D", "fs.hdfs.impl=org.apache.hadoop.hdfs.DistributedFileSystem",
// 5. 輸入/輸出路徑
"/user/input/text", // HDFS 輸入目錄
"/user/output/wc1" // HDFS 輸出目錄 (必須不存在)
};
// 執行 (RunJar 會啟動新 JVM,阻塞至 Job 完成)
org.apache.hadoop.util.RunJar.main(params);
}
}
org.apache.hadoop
hadoop-client
3.3.6
org.apache.hadoop
hadoop-hdfs
3.3.6
org.apache.hadoop
hadoop-mapreduce-client-jobclient
3.3.6
| 參數 | 用途 | 備註 |
|---|---|---|
| fs.defaultFS | 預設檔案系統 URI | HA 時用邏輯名 hdfs://nameservice |
| dfs.nameservices | NameService 列表 | 多叢集用逗號分隔 |
| dfs.ha.namenodes.xxx | 該 NS 下的 NN ID 列表 | 如 nn1,nn2 |
| dfs.namenode.rpc-address.ns.nn | 具體 NN RPC 位址 | Host:Port (通常 8020/9000) |
| dfs.client.failover.proxy.provider | 故障轉移代理實作 | 標準用 ConfiguredFailoverProxyProvider |
| yarn.resourcemanager.address | RM RPC 位址 | Client 提交 Job 用 |
| mapreduce.framework.name | 執行引擎 | yarn / local / classic |
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class SubmitJobApi {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
// ... 同樣設定 HA/YARN 參數 ...
Job job = Job.getInstance(conf, "MyWordCount");
job.setJarByClass(SubmitJobApi.class); // 打包含 Mapper/Reducer 的 Jar
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path("/user/input/text"));
FileOutputFormat.setOutputPath(job, new Path("/user/output/wc_api"));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
掌握 HA 配置與程式化提交,即可在 CI/CD 流水線、資料同步排程、微服務中無縫整合 Hadoop 生態。