在上一篇博客中: 中,开发完成的jar包需要上传到集群并使用相应的命令才能执行,这对不熟悉Linux的用户仍具有一定困难,而使用Hadoop Eclipse插件能很好的解决这一问题。

Hadoop Eclipse插件不仅能让用户直接在本地(Windows下)提交任务到Hadoop集群上,还能调试代码、查看出错信息和结果、使用图形化的方式管理HDFS文件。

Hadoop Eclipse插件需要单独从网上获取,获取后,可以自己重编译,也可直接使用编译好的release版本,经过测试,笔者发现从网上获取的插件可以直接使用,下面介绍如何获取和简单使用Eclipse插件。

获取Hadoop Eclipse插件的地址是:-eclipse-plugin

本文使用的是hadoop-2.6.4,所以使用的插件版本是hadoop-eclipse-plugin-2.6.0.jar。

在Eclipse中使用插件非常简单,对于本文所使用的Eclipse Jee版本,只需要关闭Eclipse,把上述插件复制到 Eclipse\dropins目录下,在重新打开Eclipse即可。对于其他的Eclipse版本,可能需要复制到 Eclipse\plugins 目录下。

启动Eclipse后,依次点击 Windows -> Show View -> Other。在新弹出的选项框中找到 Map/Reduce Locations, 选中后单击 OK 按钮。如下图所示:

单击 OK 后,在Eclipse下面的视图中会多出一栏 Map/Reduce Locations,如下图所示:

然后单击 Windows -> Show View -> Project Expore,在Eclipse左侧视图中会显示项目浏览器,项目浏览器中最上面会出现 DFS Locations,如下图所示:

Map/Reduce Locations 用于建立连接到Hadoop 集群,当连接到Hadoop集群后,DFS Locations 则会显示相应集群 HDFS 中的文件。 Map/Reduce Locations 可以一次连接到多个Hadoop集群。

在 Map/Reduce Locations 下侧的空白处右击,在弹出的选项中选择 New Hadoop location,新建一个Hadoop连接,之后会弹出 Hadoop location 的详细设置窗口,如下图所示,各项解释如下。

Location name: 当前建立的Hadoop location命名。

Map/Reduce Host: 为集群nomenode的IP地址。

Map/Reduce Port: MapReduce任务运行的通信端口号,客户端通过该地址向RM提交应用程序,杀死应用程序等。在yarn-site.xml中,默认值:${yarn.resourcemanager.hostname}:8032

DFS Master Use M/R Master host: 选中表示采用和 Map/Reduce Host一样的主机。

DFS Naster Host: 为集群namenode的IP地址。

DFS Master Port: HDFS端口号,对应core-site.xml中定义的fs.defaultFS参数中的端口号,一般为9000;

User Name:设置访问集群的用户名,默认为本机的用户名。

配置完成后,单击Finish即可完成 Hadoop location的配置。在 Advanced parameters选项卡中还可以配置更多细节,但在实际使用中非常繁琐,相应的设置在代码中也可以进行,或者将Hadoop集群的配置文件放到Eclipse目录下,自动完整配置。 这里只需要配置General选项卡的内容即可。这是,右侧Project Expore中的DFS locations中会多出一个子栏,名字为上面设置的Hadoop location名称。

如果前面的配置参数没有问题,Hadoop集群也已经启动,那么Eclipse插件会自动连接Hadoop集群的HDFS,并获取HDFS的文件信息。变可以在上面操作HDFS。

需要注意的是,Refresh只对选中的项目有效,如果是文件,那么只刷新该文件的相关信息;如果是文件夹,则只刷新该文件夹下的内容。

还需要值的一提的是,为了安全,HDFS的权限检测机制默认是打开的,关闭之后,才能使用Eclipse插件上传文件到HDFS或者从HDFS中删除文件。

为了能在Windows上直接操作Hadoop集群中的HDFS:

第一步:如果只在测试环境下,直接把Hadoop集群中的HDFS的权限检测关闭,可在hdfs-site.xml中添加如下变量,重启Hadoop集群即可。

<property>    <name>dfs.permissions</name>    <value>false</value></property>第二步:修改Windows本地主机名

首先,“右击”桌面上图标“我的电脑”,选择“管理”,接着选择“本地用户和组”,展开“用户”,找到当前系统用户,修改其为“hadoop"。

最后,把电脑进行“注销”或者“重启电脑”,这样修改的用户名才有效。

选用上述任意一种方法以后(如果只是学习用,推荐第一种方法),就可以用Hadoop Eclipse插件提供的图像化界面操作Hadoop集群中的HDFS了。

使用Eclipse插件可以直接在Eclipse环境下采用图形操作的方式提交任务,可以极大的简化了开发人员提交任务的步骤。

首先,需要在Eclipse中设置本地Hadoop目录,假设安装hadoop的压缩包解压到本地 F:\hadoop-2.6.4下,在Eclipse界面单击 Windows -> Preference 弹出设置界面,在设置界面找到 Hadoop Map/Reduce,在 Hadoop installation dierctory后面填上 F:\hadoop-2.6.4

此处,需要注意,解压的 F:\hadoop-2.6.4源码包是在Linux环境下的源码包,与Windows不兼容。在Windows下提交任务是会出现Failed to lacation the winutils binary in hadoop binary path,需要使用如下操作进行修复:(1) 下载Window下的运行包 将 项目下的 hadoop-2.6.4/bin目录下的所有文件覆盖掉F:\hadoop-2.6.4\bin下的所有文件。(2) 复制F:\hadoop-2.6.4\bin\hadoop.dll文件到C:\Windows\System32中。(3)配置环境变量 HADOOP_HOME为F:\hadoop-2.6.4,并将$HADOOP_HOME\bin添加到PATH环境变量中去。(4)重启电脑。

在向Hadoop集群提交任务时,还需要指定输入/输出目录,在Eclipse中,可按如下操作进行设置:双击打开工程的某代码文件,在代码编辑区 右键 -> Run As -> Run Configurations. 在弹出的窗口中找到 Java Application -> WordMain, 单击 WordMain 进入设置界面,单击 Arguments 切换选项卡,在 Program arguments 下的文本框中指定输入/输出目录。

第一行目录为输入目录,第二行目录为输出目录,格式为 hdfs://[namenode_ip]:[端口号][路径]。注意,输出目录在HDFS中不能存在。如下图所示:

注意:上图中的master我已经在本地主机的hosts文件中映射为namenode的IP地址了。

本次演示,使用 [Windows下使用eclipse编译打包运行自己的MapReduce程序 Hadoop2.6.0](下使用eclipse编译打包运行自己的MapReduce程序 Hadoop2.6.0/)中的例子。

添加配置信息有两种方法:(1) 使用con.set()方法,设置配置信息。(2) 将Hadoop集群中的修改过的配置文件,如hdfs-site.xml,core-site.xml,mapred-site.xml,yarn-site.xml,log4j.properties,复制到 WordCount 项目下的 src 文件夹下。

我比较喜欢用第二种方法。

注意:配置信息完成后,在建立Job类对象后面也新增一行代码:

job.setJar("wordcount.jar");用户告诉hadoop集群所要运行的Jar文件,所以需要先导出WordCount项目为jar文件,位置位于项目根目录下,因为上面代码job.setJar("wordcount.jar");查找目标的相对路径为WordCount项目根目录。

运行时出现的一个问题:

在通过Windows客户端向Linux服务器提交Hadoop应用时,会提示如下错误:

org.apache.hadoop.util.Shell$ExitCodeException: /bin/bash: line 0: fg: no job control        at org.apache.hadoop.util.Shell.runCommand(Shell.java:505)        at org.apache.hadoop.util.Shell.run(Shell.java:418)        at org.apache.hadoop.util.Shell$ShellCommandExecutor.execute(Shell.java:650)        at org.apache.hadoop.yarn.server.nodemanager.DefaultContainerExecutor.launchContainer(DefaultContainerExecutor.java:195)        at org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.call(ContainerLaunch.java:300)        at org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.call(ContainerLaunch.java:81)        at java.util.concurrent.FutureTask.run(FutureTask.java:262)        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)        at java.lang.Thread.run(Thread.java:745)解决方法是:在向项目文件夹下的src目录下添加的配置文件mapred-site.xml中添加如下信息:

<property>        <name>mapreduce.app-submission.cross-platform</name>        <value>true</value></property>不需要向hadoop集群的mapred-site.xml配置文件中添加。

提交任务非常简单,直接在代码编辑区 右键 -> Run As -> Run on Hadoop 即可。

在应用Hadoop Eclipse插件后,可以直接在Eclipse中建立Map/Reduce项目,该项目会自动引用相应的jar包,路径为设置的本地F:\hadoop-2.6.4目录,所以在项目中不用再进行建立lib文件夹,复制jar包等操作。

在Eclipse中一次单击 File -> New -> Project,弹出项目类型选择对话框,选择 Map/Reduce Project,单击 Next ,在新弹出的对话框中填上项目名称:wordcount2 ,单击 Finish 即可。

之后再项目中建立一个WordCount2类,插入如下代码:

package wordcount2;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;import org.apache.hadoop.util.GenericOptionsParser;public class WordCount2 {    public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{        private final static IntWritable one = new IntWritable(1);        private Text word = new Text();        @Override        protected 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();        @Override        protected 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 类: 读取hadoop的配置文件,如 site-core.xml...;                //也可以用set方法重新设置(会覆盖): conf.set("fs.defaultFS","hdfs://master:9000")                Configuration conf = new Configuration();                //将命令行中的参数自动设置到变量conf中                String[] otherArgs = new GenericOptionsParser(conf,args).getRemainingArgs();                if (otherArgs.length != 2) {                    System.err.println("Usage: wordcount <in> <out>");                    System.exit(2);                }                Job job = new Job(conf,"word count2");  //新建一个job,传入配置信息                job.setJar("wordcount2.jar");                job.setJarByClass(WordCount2.class);    //设置主类                job.setMapperClass(TokenizerMapper.class);  //设置Mapper类                job.setReducerClass(IntSumReducer.class);   //设置Reducer类                job.setOutputKeyClass(Text.class);  //设置输出类型                job.setOutputValueClass(IntWritable.class); //设置输出类型                FileInputFormat.addInputPath(job, new Path(otherArgs[0]));  //设置输入文件                FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));    //设置输出文件                boolean flag = job.waitForCompletion(true);                System.out.println("SUCCEED!"+flag);    //任务完成提示                System.exit(flag ? 0 : 1);                System.out.println();    }}之后:(1)在Eclipse设置输入/输出目录(2)导出项目jar包,存储到工程目录下,即可提交任务 Run on Hadoop.

注意,使用Map/Reduce插件建立的项目在运行时控制台并没有日志输出,所以在上面的代码最后添加一行输出 System.out.println("SUCCEED!"+flag);,当控制台最后输出SUCCEED!true时,表示任务运行成功,这是可以刷新 DFS Locations,会看到输出结果已经出来了。

本教程来自《Hadoop大数据处理技术基础与实战》--安俊秀 编著。

郑重声明:

在Windows下运行MapReduce程序,各种错误都有,如果有条件的话,建议在Linux下编程,Windows下实在麻烦。