从简单的Java程序调用mapreduce作业
我一直试图从一个简单的Java程序在同一个包中调用一个mapreduce作业。我试图在我的java程序中引用mapreduce jar文件,并使用runJar(String args[])
方法通过传递input并为mapreduce作业输出path。但程序dint工作..
我如何运行这样的程序,我只是使用传递input,输出和jarpath到它的主要方法? 是否有可能通过它来运行mapreduce作业(jar)? 我想这样做是因为我想要一个接一个地运行几个mapreduce作业,其中我的java程序vl通过引用它的jar文件来调用每个这样的作业。如果这可能,我不妨使用一个简单的servlet来做这样的调用并将其输出文件用于graphics目的..
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ /** * * @author root */ import org.apache.hadoop.util.RunJar; import java.util.*; public class callOther { public static void main(String args[])throws Throwable { ArrayList arg=new ArrayList(); String output="/root/Desktp/output"; arg.add("/root/NetBeansProjects/wordTool/dist/wordTool.jar"); arg.add("/root/Desktop/input"); arg.add(output); RunJar.main((String[])arg.toArray(new String[0])); } }
哦,请不要用runJar
,Java API是非常好的。
看看如何从正常的代码开始工作:
// create a configuration Configuration conf = new Configuration(); // create a new job based on the configuration Job job = new Job(conf); // here you have to put your mapper class job.setMapperClass(Mapper.class); // here you have to put your reducer class job.setReducerClass(Reducer.class); // here you have to set the jar which is containing your // map/reduce class, so you can use the mapper class job.setJarByClass(Mapper.class); // key/value of your reducer output job.setOutputKeyClass(Text.class); job.setOutputValueClass(Text.class); // this is setting the format of your input, can be TextInputFormat job.setInputFormatClass(SequenceFileInputFormat.class); // same with output job.setOutputFormatClass(TextOutputFormat.class); // here you can set the path of your input SequenceFileInputFormat.addInputPath(job, new Path("files/toMap/")); // this deletes possible output paths to prevent job failures FileSystem fs = FileSystem.get(conf); Path out = new Path("files/out/processed/"); fs.delete(out, true); // finally set the empty out path TextOutputFormat.setOutputPath(job, out); // this waits until the job completes and prints debug out to STDOUT or whatever // has been configured in your log4j properties. job.waitForCompletion(true);
如果您正在使用外部群集,则必须通过以下方式将以下信息添加到您的configuration中:
// this should be like defined in your mapred-site.xml conf.set("mapred.job.tracker", "jobtracker.com:50001"); // like defined in hdfs-site.xml conf.set("fs.default.name", "hdfs://namenode.com:9000");
当hadoop-core.jar
位于应用程序容器类path中时,这应该不成问题。 但是我认为你应该在网页上放一些进度指示器,因为完成一个hadoop工作可能需要几分钟到几个小时;)
对于YARN(> Hadoop 2)
对于YARN,需要设置以下configuration。
// this should be like defined in your yarn-site.xml conf.set("yarn.resourcemanager.address", "yarn-manager.com:50001"); // framework is now "yarn", should be defined like this in mapred-site.xm conf.set("mapreduce.framework.name", "yarn"); // like defined in hdfs-site.xml conf.set("fs.default.name", "hdfs://namenode.com:9000");
从Java Web应用程序调用MapReduce作业(Servlet)
您可以使用Java API从Web应用程序调用MapReduce作业。 这里是从servlet调用MapReduce作业的一个小例子。 步骤如下:
第1步 :首先创build一个MapReduce驱动程序的servlet类。 还开发地图和减less服务。 这里有一个示例代码片段:
CallJobFromServlet.java
public class CallJobFromServlet extends HttpServlet { protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException { Configuration conf = new Configuration(); // Replace CallJobFromServlet.class name with your servlet class Job job = new Job(conf, " CallJobFromServlet.class"); job.setJarByClass(CallJobFromServlet.class); job.setJobName("Job Name"); job.setOutputKeyClass(Text.class); job.setOutputValueClass(Text.class); job.setMapperClass(Map.class); // Replace Map.class name with your Mapper class job.setNumReduceTasks(30); job.setReducerClass(Reducer.class); //Replace Reduce.class name with your Reducer class job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(Text.class); job.setInputFormatClass(TextInputFormat.class); job.setOutputFormatClass(TextOutputFormat.class); // Job Input path FileInputFormat.addInputPath(job, new Path("hdfs://localhost:54310/user/hduser/input/")); // Job Output path FileOutputFormat.setOutputPath(job, new Path("hdfs://localhost:54310/user/hduser/output")); job.waitForCompletion(true); } }
第2步 :将所有相关jar(hadoop,特定于应用程序的jar文件)文件放在web服务器的lib文件夹(例如Tomcat)中。 这对于访问Hadoopconfiguration是必须的(hadoop'conf'文件夹有configurationxml文件,即core-site.xml,hdfs-site.xml等)。 只需将hadoop lib文件夹中的jar文件复制到web服务器(tomcat)lib目录即可。 jar子名称列表如下:
1. commons-beanutils-1.7.0.jar 2. commons-beanutils-core-1.8.0.jar 3. commons-cli-1.2.jar 4. commons-collections-3.2.1.jar 5. commons-configuration-1.6.jar 6. commons-httpclient-3.0.1.jar 7. commons-io-2.1.jar 8. commons-lang-2.4.jar 9. commons-logging-1.1.1.jar 10. hadoop-client-1.0.4.jar 11. hadoop-core-1.0.4.jar 12. jackson-core-asl-1.8.8.jar 13. jackson-mapper-asl-1.8.8.jar 14. jersey-core-1.8.jar
步骤3 :将您的Web应用程序部署到Web服务器(在Tomcat的'webapps'文件夹中)。
第4步 :创build一个jsp文件,并在表单action属性中链接servlet类(CallJobFromServlet.java)。 这里有一个示例代码片段:
的index.jsp
<form id="trigger_hadoop" name="trigger_hadoop" action="./CallJobFromServlet "> <span class="back">Trigger Hadoop Job from Web Page </span> <input type="submit" name="submit" value="Trigger Job" /> </form>
Hadoop示例中已经实现的作业的另一种方法,也需要导入hadoopjar..然后只需要调用所需作业类的静态主函数与适当的String []参数
由于map和reduce在不同的机器上运行,所有引用的类和jar都必须从机器移动到机器。
如果你有包jar,并在你的桌面上运行,@ ThomasJungblut的答案是好的。 但是,如果你在Eclipse中运行,右键单击你的类并运行,它不起作用。
代替:
job.setJarByClass(Mapper.class);
使用:
job.setJar("build/libs/hdfs-javac-1.0.jar");
同时,你的jar的清单必须包含Main-Class属性,这是你的主类。
对于Gradle用户,可以将这些行放在build.gradle中:
jar { manifest { attributes("Main-Class": mainClassName) }}
我想不出有多less方法可以做到这一点,而不涉及哈多普核心库(或者实际上@ThomasJungblut说,为什么你会想)。
但是,如果您绝对必须,您可以为您的工作设置一个带有工作stream程的Oozie服务器,然后使用Oozie Web服务界面将工作stream程提交给Hadoop。
- http://yahoo.github.com/oozie/
- http://yahoo.github.com/oozie/releases/2.3.0/WorkflowFunctionalSpec.html#a11.3.1_Job_Submission
再次,这似乎是很多工作的东西,可以使用托马斯的答案解决(包括hadoop核心jar和使用他的代码片段)
你可以这样做
public class Test { public static void main(String[] args) throws Exception { int res = ToolRunner.run(new Configuration(), new YourJob(), args); System.exit(res); }