我目前正在使用 maven 进行依赖项管理。
在这种情况下,我编写了一个将 map-reduce 作业提交给 hadoop 的方法,然后为此方法编写了一个 junit 测试。
当我跑步时mvn package
它编译成功(所有依赖项都是正确的)它是失败的单元测试。
在工作跟踪器上,我可以看到ClassNotFoundException
表明我的地图、组合和减少类在节点上找不到。
我不想用conf.setJar
用来手动设置这个 jar 文件的路径。
有什么办法可以让它自动工作吗?
您需要一种机制,您的用户代码(映射器、组合器、reducer 类等)可以通过该机制提供给 TaskTracker。这通常通过将您的类捆绑到一个 jar 文件中然后使用setJar
/setJarByClass
方法来处理。在后台,hadoop 会将这个 jar 上传到 HDFS 中的一个 tmp 作业目录,并将 tmp HDFS 作业 jar 添加到分布式缓存中。
我的建议是将你的单元测试变成集成测试——maven 生命周期中的这个阶段发生在打包之后,你将拥有一个 jar,然后你可以调用 setJar 并知道你将构建一个 jar(我是在这里猜测您不想在普通测试阶段调用 setJar ,因为该 jar 尚未构建)。
最后,如果您想测试您的映射器/reducer 代码而不在真正的集群中运行,您应该查看MRUnit或在 hadoop 本地模式下运行作业 - 这两种方法都不需要您构建一个 jar。
作为参考,这是一个在本地模式下运行的最小 JUnit 片段,可在我的 Ubuntu 桌面上运行(如果您的桌面是 Windows,则需要安装 cygwin 或 unxutils)。它不是单元测试,因为它没有断言输出:
@Test
public void testLocalRun() throws IOException, InterruptedException, ClassNotFoundException {
Job job = new Job();
job.setInputFormatClass(TextInputFormat.class);
FileInputFormat.setInputPaths(job,
"src/test/java/csw/hadoop/sandbox/LocalHadoopTest.java");
job.setOutputFormatClass(TextOutputFormat.class);
TextOutputFormat.setOutputPath(job, new Path(
"target/hadoop-local-output"));
job.setNumReduceTasks(0);
job.waitForCompletion(true);
}