我需要向Hadoop提交几个相关的工作(这就是为什么它们由相同的驱动程序类启动)但完全相互独立。现在我开始这样的工作:
int res = ToolRunner.run(new Configuration(), new MapReduceClass(params), args);
运行作业,获取返回代码,然后继续。
我想做的是提交几个这样的作业并行运行,检索每个作业的返回码。
显而易见(对我而言)的想法是启动多个线程,每个线程负责一个hadoop工作,但我想知道hadoop是否有更好的方法来实现这一目标?我没有任何编写并发代码的经验,所以我宁愿不花很多时间来学习它的复杂性,除非这里有必要。
答案 0 :(得分:3)
这可能是一个建议,但暗示代码,所以我会把它作为答案。
在这段代码(个人代码)中,我只是遍历一些变量,并多次提交一份工作(同一份工作)。
使用job.waitForCompletion(false)将帮助您提交多个作业。
while (processedInputPaths < inputPaths.length) {
if (processedInputPaths + inputPathsLimit < inputPaths.length) {
end = processedInputPaths + inputPathsLimit - 1;
} else {
end = inputPaths.length - 1;
}
start = processedInputPaths;
Job job = this.createJob(configuration, inputPaths, cycle, start, end, outputPath + "/" + cycle);
boolean success = job.waitForCompletion(true);
if (success) {
cycle++;
processedInputPaths = end + 1;
} else {
LOG.info("Cycle did not end successfully :" + cycle);
return -1;
}
}
答案 1 :(得分:1)
psabbate的回答让我找到了我遗失的几个API。这就是我解决它的方法:
在驱动程序类中,使用以下代码启动作业:
List<RunningJob> runningJobs = new ArrayList<RunningJob>();
for (String jobSpec: jobSpecs) {
// Configure, for example, a params map that gets passed into the MR class's constructor
ToolRunner.run(new Configuration(), new MapReduceClass(params, runningJobs), null);
}
for (RunningJob rj: runningJobs) {
System.err.println("Waiting on job "+rj.getID());
rj.waitForCompletion();
}
然后,在MapReduceClass中,定义一个私有变量List<RunningJob> runningJobs
,定义一个这样的构造函数:
public MergeAndScore(Map<String, String> p, List<RunningJob> rj) throws IOException {
params = Collections.unmodifiableMap(p);
runningJobs = rj;
}
在run()
调用的ToolRunner
方法中,定义您的JobConf
并使用
JobClient jc = new JobClient();
jc.init(conf);
jc.setConf(conf);
runningJobs.add(jc.submitJob(conf));
这样,run()
立即返回,并且可以通过驱动程序类中的runningJobs
对象访问作业。
请注意,我正在处理旧版本的Hadoop,因此jc.init(conf)
和/或jc.setConf(conf)
可能需要或可能不需要,具体取决于您的设置,但可能至少需要其中一个。