【问题标题】:Running MapReduce remotely远程运行 MapReduce
【发布时间】:2015-03-26 00:06:31
【问题描述】:

我有一个远程运行的 hadoop 集群。我能够完成教程:

http://hadoop.apache.org/docs/r2.6.0/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html

在我的远程机器上,因为有一个内置的 hadoop 实例。但是,我希望在本地执行相同的任务。作为hadoop的新手,我不知道该怎么做。我想知道我是否可以运行该程序并将结果发送回我的本地计算机。我不确定如何登录到我的远程计算机然后运行 ​​MapReduce 作业。

这是我远程机器上的代码:

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordCount {
    public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{

        private final static IntWritable one = new IntWritable(1);
        private Text word = new Text();

        public void map(Object key, Text value, Context context
        ) throws IOException, InterruptedException {
            StringTokenizer itr = new StringTokenizer(value.toString());
            while (itr.hasMoreTokens()) {
                word.set(itr.nextToken());
                context.write(word, one);
            }
        }
    }

    public static class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> {
        private IntWritable result = new IntWritable();

        public void reduce(Text key, Iterable<IntWritable> values,
                           Context context
        ) throws IOException, InterruptedException {
            int sum = 0;
            for (IntWritable val : values) {
                sum += val.get();
            }
            result.set(sum);
            context.write(key, result);
        }
    }

    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf, "word count");
        conf.set("mapred.job.queue.name", "exp_dsa");
        job.setJarByClass(WordCount.class);
        job.setMapperClass(TokenizerMapper.class);
        job.setCombinerClass(IntSumReducer.class);
        job.setReducerClass(IntSumReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

【问题讨论】:

    标签: java hadoop mapreduce


    【解决方案1】:

    我知道这对你来说有点晚了,但人们肯定可以从我的回复中受益,因为我正在寻找非常相似的设置并且能够远程运行作业(甚至从 Eclipse)。

    首先让我提一下,您的机器上不需要任何 Hadoop 分发版即可远程提交作业(至少在 Hadoop 2.6.0 中,根据发布信息和发布日期,这在您的情况下似乎没问题问题)。我将解释如何从 Eclipse 运行作业。

    让我从配置开始。很少有资源可以提供一些关于如何实现这一点的信息,但是没有其他解决方案提供的解决方案对我有用,没有额外的配置。

    在服务器上。

    1. 假设您安装了 Hadoop、Yarn 和 HDFS,您的第一步应该是正确配置系统变量(当然稍后您将需要它们)。我建议编辑名为hadoop-env.sh 的文件(在我的情况下位于/etc/hadoop/conf/)并包含以下几行:

      export HADOOP_CONF_DIR=/etc/hadoop/conf/
      export HADOOP_COMMON_HOME=/usr/lib/hadoop/
      export HADOOP_HDFS_HOME=/usr/lib/hadoop-hdfs/
      export HADOOP_YARN_HOME=/usr/lib/hadoop-yarn/
      export HADOOP_MAPRED_HOME=/usr/lib/hadoop-mapreduce/
      

      (其中/usr/lib/hadoop/ 对应于安装Hadoop 的目录)。重启服务。

    2. core-site.xml中,你应该有如下配置:fs.defaultFS,在某处记下它并检查防火墙是否有开放的端口,以便外部客户端可以执行数据相关的操作。如果您没有此配置,请在文件中添加以下条目:

      <property>
          <name>fs.defaultFS</name>
          <value>hdfs://<host-name></value>
          <final>true</final>
      </property>
      
    3. 假设您已正确配置 namenode (s) 和 datanode (s)。编辑 yarn-site.xml 文件并添加以下条目(或检查它们是否存在并记下配置)

      <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
      </property>
      <property>
        <name>yarn.nodemanager.aux-services.mapreduce_shuffle.class</name>
        <value>org.apache.hadoop.mapred.ShuffleHandler</value>
      </property>
      <property>
        <name>yarn.resourcemanager.address</name>
        <value><your-hostname>:8050</value>
      </property>
      <property>
        <name>yarn.application.classpath</name>
        <value>
          $HADOOP_CONF_DIR,
          $HADOOP_COMMON_HOME/*,$HADOOP_COMMON_HOME/lib/*,
          $HADOOP_HDFS_HOME/*,$HADOOP_HDFS_HOME/lib/*,
          $HADOOP_MAPRED_HOME/*,$HADOOP_MAPRED_HOME/lib/*,
          $HADOOP_YARN_HOME/*,$HADOOP_YARN_HOME/lib/*
        </value>
      </property>
      

      (查看Hadoop documentation了解不同配置的含义)

    4. 使用以下条目修改mapred-site.xml 文件:

      <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
      </property>
      <property>
        <name>yarn.app.mapreduce.am.staging-dir</name>
        <value>/user</value>
      </property>
      
    5. 重新启动服务。服务器基本上准备好了。检查是否所有需要的端口都可以从外部访问(在下面的web-site 上有相当完整的列表,只是其中一些应该是打开的,请咨询您的系统管理员)

    在客户端

    在 Eclipse 中创建一个项目(简单的 Java 应用程序)。创建你的 Mapper 和 Reducer(有很多教程我不会在这里给出任何例子)。现在在 Main 类中,您应该为您的工作提供以下配置(它可能会有所不同,具体取决于您的安全性和系统限制,因此如果您无法远程连接到服务器计算机,您可能应该自己挖掘)

    Configuration conf = new Configuration();
    conf.set("yarn.resourcemanager.address", "<your-hostname>:8050"); // see step 3
    conf.set("mapreduce.framework.name", "yarn"); 
    conf.set("fs.defaultFS", "hdfs://<your-hostname>/"); // see step 2
    conf.set("yarn.application.classpath",        
                 "$HADOOP_CONF_DIR,$HADOOP_COMMON_HOME/*,$HADOOP_COMMON_HOME/lib/*,"
                    + "$HADOOP_HDFS_HOME/*,$HADOOP_HDFS_HOME/lib/*,"
                    + "$HADOOP_YARN_HOME/*,$HADOOP_YARN_HOME/lib/*,"
                    + "$HADOOP_MAPRED_HOME/*,$HADOOP_MAPRED_HOME/lib/*");
    
    Job job = Job.getInstance(conf);
    if (args.length>0) {
        job.setJar(args[0]); // see below, use this when submitting from Eclipse
    } else { 
        job.setJarByClass(HadoopWorkloadMain.class); // use this when uploaded the Jar to the server and running the job directly and locally on the server
    }
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(DoubleWritable.class);
    job.setMapperClass(SomeMapper.class);
    job.setCombinerClass(SomeReducer.class);
    job.setReducerClass(SomeReducer.class);
    
    FileInputFormat.addInputPath(job, new Path("/inputs/")); // existing HDFS directory
    FileOutputFormat.setOutputPath(job, new Path("/results/")); // not existing HDFS directory
    
    job.waitForCompletion(true);
    

    classpath配置必须按照this resource设置。

    这应该可以解决问题。运行您的 main 并查看 Hadoop 工作。无论如何,我祝你好运和耐心,这听起来很容易的任务可能需要相当大的努力。

    疑难解答:

    1. 除了要包含在客户端构建路径中的明显 Jars 之外,您可能需要添加不太明显的 Jars,请查看此 SO Question 以了解您应该另外包含哪些内容。

    【讨论】:

    【解决方案2】:

    我对 hadoop 2.7 有同样的挑战,并通过添加以下配置解决了它。

    conf.set("yarn.resourcemanager.address", "127.0.0.1:8032"); 
    conf.set("mapreduce.framework.name", "yarn");
    conf.set("fs.default.name", "hdfs://127.0.0.1:9000");
    conf.set("mapreduce.job.jar",".\\target\\wc-mvn-0.0.1-SNAPSHOT.jar");
    

    【讨论】:

      【解决方案3】:

      要实现这一点,您需要在本地拥有相同的 Hadoop Distribution 副本和 Namenode 上的配置文件(core-site.xml、hdfs-site.xml 和 mapred-site.xml)。

      然后您可以使用 hadoop 命令从您的机器向远程集群提交作业。

      【讨论】:

      • 你会不会碰巧知道一些资源/教程,我可以在其中了解更多信息?
      • 你可以从这个tutorial开始
      【解决方案4】:

      除了 Serhiy 建议的所有步骤外,还必须按照下面文章中的建议使用 WinUtils(如果用户在 Windows 上运行 Eclipse)

      Spark 1.6-Failed to locate the winutils binary in the hadoop binary path

      并将 HADOOP_HOME 路径作为系统变量设置为 /bin 目录。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-27
        • 2012-06-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多