paulwong

          Submitting a Hadoop MapReduce job to a remote JobTracker

          While messing around with MapReduce code, I’ve found it to be a bit tedious having to generate the jarfile, copy it to the machine running the JobTracker, and then run the job every time the job has been altered. I should be able to run my jobs directly from my development environment, as illustrated in the figure below. This post explains how I’ve “solved” this problem. This may also help when integrating Hadoop with other applications. I do by no means claim that this is the proper way to do it, but it does the trick for me.

          My Hadoop infrastructure


          I assume that you have a (single-node) Hadoop 1.0.3 cluster properly installed on a dedicated or virtual machine. In this example, the JobTracker and HDFS resides on IP address 192.168.102.131.Let’s start out with a simple job that does nothing except to start up and terminate:

          package com.pcbje.hadoopjobs;

          import java.io.IOException;
          import java.util.Date;
          import java.util.Iterator;
          import org.apache.hadoop.conf.Configuration;
          import org.apache.hadoop.fs.Path;
          import org.apache.hadoop.io.IntWritable;
          import org.apache.hadoop.io.LongWritable;
          import org.apache.hadoop.io.Text;
          import org.apache.hadoop.mapred.FileInputFormat;
          import org.apache.hadoop.mapred.FileOutputFormat;
          import org.apache.hadoop.mapred.JobClient;
          import org.apache.hadoop.mapred.JobConf;
          import org.apache.hadoop.mapred.MapReduceBase;
          import org.apache.hadoop.mapred.Mapper;
          import org.apache.hadoop.mapred.OutputCollector;
          import org.apache.hadoop.mapred.Reporter;
          import org.apache.hadoop.mapreduce.Job;
          import org.apache.hadoop.mapred.Reducer;

          public class MyFirstJob {
          public static void main(String[] args) throws Exception {
          Configuration config
          = new Configuration();

          JobConf job
          = new JobConf(config);
          job.setJarByClass(MyFirstJob.
          class);
          job.setJobName(
          "My first job");

          FileInputFormat.setInputPaths(job,
          new Path(args[0));
          FileOutputFormat.setOutputPath(job,
          new Path(args[1]));

          job.setMapperClass(MyFirstJob.MyFirstMapper.
          class);
          job.setReducerClass(MyFirstJob.MyFirstReducer.
          class);

          JobClient.runJob(job);
          }


          private static class MyFirstMapper extends MapReduceBase implements Mapper {
          public void map(LongWritable key, Text value, OutputCollector output, Reporter reporter) throws IOException {

          }

          }


          private static class MyFirstReducer extends MapReduceBase implements Reducer {
          public void reduce(Text key, Iterator values, OutputCollector output, Reporter reporter) throws IOException {

          }

          }

          }


          Now, most of the examples you find online typically shows you a local mode setup where all the components of Hadoop (HDFS, JobTracker, etc) run on the same machine. A typical mapred-site.xml configuration might look like:

          <configuration>
          <property>
          <name>mapred.job.tracker</name>
          <value>localhost:9001</value>
          </property>
          </configuration>

          As far as I can tell, such a configuration requires that jobs are submitted from the same node as the JobTracker. This is what I want to avoid. The first thing to do is to change the fs.default.name attribute to the IP address of my NameNode.

          Configuration conf = new Configuration();
          conf.set(
          "fs.default.name", "192.168.102.131:9000");

          And in core-site.xml:

          <configuration>
             
          <property>
                 
          <name>fs.default.name</name>
                 
          <value>192.168.102.131:9000</value>
             
          </property>
          </configuration>

          This tells the job to connect to the HDFS residing on a different machine. Running the job with this configuration will read from and write to the remote HDFS correctly, but the JobTracker at 192.168.102.131:9001 will not notice it. This means that the admin panel at 192.168.102.131:50030 wont list the job either. So the next thing to do is to tell the job configuration to submit the job to the appropriate JobTracker like this:

          config.set("mapred.job.tracker", "192.168.102.131:9001");

          You also need to change mapred-site.xml to allow external connections, this can be done by replacing “localhost” with the JobTracker’s IP address:
          <configuration>
             
          <property>
                 
          <name>mapred.job.tracker</name>
                 
          <value>192.168.102.131:9001</value>
             
          </property>
          </configuration>

          Restart hadoop.Upon trying to run your job, you may get an exception like this:
          SEVERE: PriviledgedActionException as:[user] cause:org.apache.hadoop.security.AccessControlException:
          org.apache.hadoop.security.AccessControlException: Permission denied: user=[user], access=WRITE, inode="mapred":root:supergroup:rwxr-xr-x
          
          If you do, this may be solved by adding the following mapred-site.xml:
          <configuration>
             
          <property>
                 
          <name>mapreduce.jobtracker.staging.root.dir</name>
                 
          <value>/user</value>
             
          </property>
          </configuration>

          And then execute the following commands:
          stop-mapred.sh
          start-mapred.sh
          
          When you now submit your job, it should be picked up by the admin page over at :50030. However, it will most probably fail and the log will be telling you something like:
          java.lang.ClassNotFoundException: com.pcbje.hadoopjobs.MyFirstJob$MyFirstMapper
          
          In order to fix this, you have to ensure that all dependencies of the submitted job are available to the JobTracker. This can be achieved by exporting the project in as a runnable jar, and then execute something like: 
          java -jar myfirstjob-jar-with-dependencies.jar /input/path /output/path
          
          If your user has the appropriate permissions to the input and out directory on HDFS, the job should now run successfully. This can be verified in the console and on the administration panel.

          Manually exporting runnable jars requires a lot of clicks in IDEs such as Eclipse. If you are using Maven, you can tell it to build the jar with its dependencies (See this answer for details). This would make the process a whole lot easier.Finally, to make it even easier, place a tiny bash-script in the same folder as pom.xml for building the maven project and executing the jar:
          #!/bin/sh
          mvn assembly:assembly
          java -jar $1 $2 $3
          
          After making the script executable, you can build and submit the job with the following command:
          ./build-and-run-job target/myfirstjob-jar-with-dependencies.jar /input/path 

          posted on 2012-10-03 15:06 paulwong 閱讀(770) 評論(0)  編輯  收藏 所屬分類: HADOOP云計算HBASE

          主站蜘蛛池模板: 孝感市| 元江| 兴国县| 灌阳县| 三台县| 黎川县| 腾冲县| 河津市| 浙江省| 景德镇市| 浠水县| 固原市| 同心县| 青河县| 治多县| 杂多县| 宝兴县| 远安县| 通化县| 阜城县| 榕江县| 宜春市| 柯坪县| 宁阳县| 陈巴尔虎旗| 盖州市| 奎屯市| 上栗县| 达州市| 凤凰县| 文化| 社旗县| 赞皇县| 冷水江市| 台湾省| 江阴市| 宁国市| 浦城县| 永新县| 高密市| 上虞市|