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

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

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

一、获取Hadoop Eclipse插件

获取Hadoop Eclipse插件的地址是:https://github.com/winghc/hadoop2x-eclipse-plugin

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

二、使用Hadoop Eclipse插件

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

1.查找Eclipse插件

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

![](http://i.imgur.com/cIfR0k2.png)

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

![](http://i.imgur.com/Fue1psJ.png)

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

![](http://i.imgur.com/rSfDgLQ.png)

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:设置访问集群的用户名,默认为本机的用户名。
![](http://i.imgur.com/okOUyOd.png)

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

2.使用Eclipse插件管理HDFS

如果前面的配置参数没有问题,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了。

![](http://i.imgur.com/OhPtnF6.png)

三、在Eclipse中提交任务到Hadoop

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

1.配置本地Hadoop目录和输入输出目录

首先,需要在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下的运行包
https://github.com/steveloughran/winutils/项目下的 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中不能存在。如下图所示:

![](http://i.imgur.com/4GjcRmn.png)

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

为WordCount添加配置信息。

本次演示,使用 [Windows下使用eclipse编译打包运行自己的MapReduce程序 Hadoop2.6.0](http://freeshow.github.io/2016/07/24/Windows下使用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配置文件中添加。

3.提交任务

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

四、建立Map/Reduce项目

在应用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下实在麻烦。

更多精彩内容,欢迎关注微信公众号: 不会搬砖的码农
不会搬砖的码农

Logo

更多推荐