(工程整理)如何用Maven构建Hadoop项目

本人去年的时候一直对maven项目很头疼,由于在构建hadoop项目时涉及到很多版本冲突方面的问题,但是在今年的开发中将很多问题得以解决。这一次,将本人的经验得以总结,为大家讲解一下用maven构建hadoop项目的具体步骤。

(一)hadoop家族简介


Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahout, Zookeeper, Avro, Ambari, Chukwa,新增加的项目包括,YARN, Hcatalog, Oozie, Cassandra, Hama, Whirr, Flume, Bigtop, Crunch, Hue等。

从2011年开始,中国进入大数据风起云涌的时代,以Hadoop为代表的家族软件,占据了大数据处理的广阔地盘。开源界及厂商,所有数据软件,无一不向Hadoop靠拢。Hadoop也从小众的高富帅领域,变成了大数据开发的标准。在Hadoop原有技术基础之上,出现了Hadoop家族产品,通过“大数据”概念不断创新,推出科技进步。作为IT界的开发人员,我们也要跟上节奏,抓住机遇,跟着Hadoop一起雄起!

参考资料:http://blog.fens.me/series-hadoop-family/

(二)Maven构建Hadoop

0. 前言

Hadoop的MapReduce是一个复杂的编程环境,所以要尽可能简化构建MapReduce项目的过程。Maven是一个很不错的自动化项目构建工具,通过Maven帮助我们从复杂的环境配置中解脱出来,从而标准化开发过程。因此,写MR之前,我们先花点时间把刀磨快!!当然,除了Maven还有其他的选择Gradle(推荐),Ivy等。后面会有介绍几篇MapReduce开发的文章,都要依赖于本文中Maven的构建的MapReduce环境。

1. Maven介绍
Apache Maven,是一个Java的项目管理及自动构建的工具,由Apache软件基金会所提供。基于项目对象模型(缩写:POM)的概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。曾是Jakarta项目的子项目,现为独立Apache项目。
Maven的目标是使得项目的构建更加容易,它把编译、打包、测试、发布等开发过程中的不同环节有机的串联了起来,并产生一致的、高质量的项目信息,使得项目成员能够及时地得到反馈。maven有效地支持了测试优先、持续集成,体现了鼓励沟通,及时反馈的软件开发理念。如果说Ant的复用是建立在”拷贝–粘贴”的基础上的,那么Maven通过插件的机制实现了项目构建逻辑的真正复用。

2. Maven安装(win)
下载Maven:http://maven.apache.org/download.cgi

下载最新的xxx-bin文件(例如:apache-maven-3.5.2-bin.tar.gz),在win上解压到 E:\HadoopWorkPlat\apache-maven-3.5.2。


并把maven/bin目录设置在环境变量PATH中:先创建系统变量MAVEN_HOME,将E:\HadoopWorkPlat\apache-maven-3.5.2赋值给MAVEN_HOME变量,再将%MAVEN_HOME%/bin添加到系统的Path中,如下所示。



确定之后,打开命令行输入mvn命令,我们会看到mvn命令的运行效果,表明maven已经安装成功。


接下来需要安装Eclipse的Maven插件,下载地址:http://www.eclipse.org/m2e/,安装完成后,打开windows -> Preferences,Maven的Eclipse插件配置如下(注意,需要配置两个setting文件,可以选择相同的setting路径,也可以不同)


3.Hadoop 开发环境介绍

如图所示,我们可以选择在windows中开发,也可以在linux中开发,可以选择则在本地启动Hadoop或者远程调用Hadoop,标配的工具都是Maven和Eclipse。

4.用Maven构建Hadoop环境
(1)用Maven创建一个标准化的Java项目;(2)导入项目到eclipse;(3)增加hadoop依赖,修改pom.xml;(4)下载依赖;(5)从Hadoop集群环境下载hadoop配置文件;(6)配置本地host。

(1)用Maven创建一个标准化的Java项目

在指定的路径x输入以下命令,maven就会自动下载一个项目:

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=org.conan.myhadoop.mr
-DartifactId=myHadoop -DpackageName=org.conan.myhadoop.mr -Dversion=1.0-SNAPSHOT -DinteractiveMode=false
(2)导入项目到eclipse:

我们创建好了一个基本的maven项目,然后导入到eclipse中。 这里我们最好已安装好了Maven的插件。


(3)在pom.xml中添加hadoop依赖

<properties>
	<hadoop.version>2.6.0</hadoop.version>
</properties>
<dependency>
	<groupId>org.apache.hadoop</groupId>
	<artifactId>hadoop-client</artifactId>
	<version>${hadoop.version}</version>
</dependency>

<dependency>
	<groupId>org.apache.hadoop</groupId>
	<artifactId>hadoop-common</artifactId>
	<version>${hadoop.version}</version>
</dependency>

<dependency>
	<groupId>org.apache.hadoop</groupId>
	<artifactId>hadoop-hdfs</artifactId>
	<version>${hadoop.version}</version>
</dependency>

(4)下载依赖:mvn clean install


项目的依赖程序,被自动加载的库路径下面。

(5)从Hadoop集群环境中下载hadoop的相关配置文件:core-site.xml、hdfs-site.xml、mapred-site.xml,并将它们保存在src/main/resources/hadoop目录下面,同时delete掉原自动生成的文件:App.java和AppTest.java。


(6)配置本地host,增加master的域名指向:进入目录C:\Windows\System32\drivers\etc,打开hosts,配置master的域名指向:


5 一个简单的MapReduce程序开发

public class WordCounterJob {

	private static Configuration getBigdataConfig() {
		Configuration conf = HBaseConfiguration.create();
		conf.addResource("/usr/local/hadoop/hadoop-2.7.3/etc/hadoop/core-site.xml");
		conf.set("fs.default.name", "hdfs://192.168.106.102:9000");
		conf.set("hbase.zookeeper.property.clientPort", "2181");
		conf.set("hbase.zookeeper.quorum", "192.168.106.102");
		conf.set("hbase.master", "192.168.106.102:16010");
		conf.set("hbase.rpc.timeout", "2000");
		conf.set("hbase.client.retries.number", "5");
		conf.set("dfs.socket.timeout", "180000");
		conf.set("zookeeper.session.timeout", "180000");
		conf.set("hbase.client.scanner.timeout.period", "240000");
		conf.set("hbase.client.retries.number", "100");
		conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
		conf.set("mapreduce.tasktracker.map.tasks.maximum", "7");
		conf.set("mapreduce.tasktracker.reduce.tasks.maximum", "4");
		conf.set("mapreduce.job.reduces", "4");
		conf.set("mapred.compress.map.output", "true");
		return conf;
	}

	protected static class WordCounterMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
		String name;
		String company;
		IntWritable one;
		Text outKey;

		@Override
		protected void setup(Context context) throws IOException, InterruptedException {
			// TODO Auto-generated method stub
			Configuration conf = context.getConfiguration();
			name = conf.get("my.name", "null");
			company = conf.get("my.company", "null");
			one = new IntWritable(1);
			outKey = new Text();
		}

		@Override
		protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
			// TODO Auto-generated method stub
			outKey.set(name);
			context.write(outKey, one);
			outKey.set(company);
			context.write(outKey, one);

			String line = new String(value.getBytes(), 0, value.getLength(), "GBK");
			String[] tokens = line.split("\\s+");
			for (String token : tokens) {
				int mid = token.indexOf("/");
				if (mid != -1) {
					String word = token.substring(0, mid);
					word = word.replace("[", "").replace("]", "");
					if (word.matches("[\u4e00-\u9fa5]+")) {
						outKey.set(word);
						context.write(outKey, one);
					}
				}
			}
		}
	}
	
	protected static class MyPartitioner extends Partitioner<Text, IntWritable> {

		@Override
		public int getPartition(Text key, IntWritable value, int numPartitions) {
			// TODO Auto-generated method stub
			return 0;
		}
		
		
	}
	
	protected static class WordCounterReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
		@Override
		protected void reduce(Text arg0, Iterable<IntWritable> arg1, Context arg2)
				throws IOException, InterruptedException {
			// TODO Auto-generated method stub
			int sum = 0;
			for (IntWritable i : arg1) {
				sum += i.get();
			}
			arg2.write(arg0, new IntWritable(sum));
		}
	}

	private static void run(String[] args) throws Exception {
		// TODO Auto-generated method stub
		Configuration conf = getBigdataConfig();
		System.out.println(conf.get("fs.default.name"));
		conf.setStrings("my.name", "wangyanyan");
		conf.setStrings("my.company", "cnki");
		Job job = Job.getInstance(conf);
		job.setJarByClass(WordCounterJob.class);
		job.setJobName("WordCounterJob");

		job.setInputFormatClass(TextInputFormat.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(IntWritable.class);

		job.setMapperClass(WordCounterMapper.class);
		job.setReducerClass(WordCounterReducer.class);
		job.setCombinerClass(WordCounterReducer.class);
		job.setNumReduceTasks(2);
		
		Path outputPath = new Path(args[1]);
		FileSystem fs = FileSystem.get(conf);
		if (fs.exists(outputPath)) {
			fs.delete(outputPath, true);
		}

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

		long t0 = System.currentTimeMillis();
		boolean b = job.waitForCompletion(true);
		if (!b) {
			throw new IOException("error with job!");
		} else {
			long t1 = System.currentTimeMillis();
			System.out.println(">> Running success, " + (t1 - t0) / 60000.0 + " min");
		}
	}

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		args = new String[] { "hdfs://192.168.106.102:9000/wangyanyan/count/in",
				"hdfs://192.168.106.102:9000/wangyanyan/count/out" };
		run(args);
	}

}
查看运行结果:
wangyanyan	10000
一万	2
一下	9
一下子	7
一九九七年	6
一九九八年	4
一九五六	1
一九八二年	1
一体化	9
一千	3
......
这样,我们就实现了在win7中的开发,通过Maven构建Hadoop依赖环境,在Eclipse中开发MapReduce的程序,然后运行JavaAPP。Hadoop应用会自动把我们的MR程序打成jar包,再上传的远程的hadoop环境中运行,返回日志在Eclipse控制台输出。

猜你喜欢

转载自blog.csdn.net/little_fire/article/details/80728395
今日推荐