我一直在尝试从同一个包中的一个简单java程序调用mapreduce作业。。我试图在我的java程序中引用mapreduce jar文件,并使用runJar(String args[])
方法调用它,同时传递mapreduce作业的输入和输出路径。。但是程序力工作。。
我如何运行这样一个程序,我只使用传递输入,输出和jar路径到它的主方法??有可能通过它运行mapreduce作业(jar)吗??我之所以想这样做,是因为我想一个接一个地运行几个mapreduce作业,其中我的java程序vl通过引用其jar文件来调用每个这样的作业。。如果可能的话,我还不如使用一个简单的servlet来进行这样的调用,并为图形目的引用它的输出文件。。
/*
* 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);
如果您使用的是外部集群,您必须通过将以下信息放入您的配置中
// 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
位于应用程序容器类路径中时,这应该没有问题。但我认为你应该在你的网页上放一些进度指示器,因为完成一个hadoop工作可能需要几分钟到几个小时;)
对于YARN(>Hadoop 2)
对于YARN,需要设置以下配置。
// 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应用程序(Servlet)调用MapReduce作业
您可以使用Java API从web应用程序调用MapReduce作业。下面是一个从servlet调用MapReduce作业的小示例。步骤如下:
步骤1:首先创建一个MapReduce驱动程序servlet类。还开发了地图&减少服务。下面是一个示例代码片段:
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服务器(例如Tomcat)的lib文件夹中。这对于访问Hadoop配置是强制性的(Hadoop‘conf’文件夹有配置xml文件,即core-site.xml、hdfs-site.xml等)。只需将jar从hadooplib文件夹复制到web服务器(tomcat)lib目录即可。罐子名称列表如下:
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:创建一个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示例中实现的作业的方法,它还需要导入hadoop jar。。然后只需使用参数
因为映射和减少在不同的机器上运行,所以所有引用的类和jar都必须从一台机器移动到另一台机器。
如果你有package jar,并在桌面上运行,@ThomasJungblut的答案是可以的。但如果你在Eclipse中运行,右键单击你的类并运行,它就不起作用了。
代替:
job.setJarByClass(Mapper.class);
用途:
job.setJar("build/libs/hdfs-javac-1.0.jar");
和此同时,jar的清单必须包含MainClass属性,它是您的主类。
对于gradle用户,可以将这些行放在build.gradle:中
jar {
manifest {
attributes("Main-Class": mainClassName)
}}
我想不出有多少方法可以在不涉及hadoop核心库的情况下做到这一点(或者确实像@ThomasJungblut所说的那样,为什么你想这样做)。
但是,如果你必须这样做,你可以为你的工作设置一个Oozie服务器和一个工作流,然后使用Oozie Web服务接口将工作流提交给Hadoop。
- http://yahoo.github.com/oozie/
- http://yahoo.github.com/oozie/releases/2.3.0/WorkflowFunctionalSpec.html#a11.3.1_Job_Submission
同样,对于那些可以使用Thomas的答案(包括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);
}