Hadoop简介
一、用Maven构建Hadoop项目
Hadoop家族系列文章(http://blog.fens.me/series-hadoop-family/),主要介绍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一起雄起!
1、前言
Hadoop的MapReduce环境是一个复杂的编程环境,所以我们要尽可能地简化构建MapReduce项目的过程。Maven是一个很不错的自动化项目构建工具,通过Maven来帮助我们从复杂的环境配置中解脱出来,从而标准化开发过程。所以,写MapReduce之前,让我们先花点时间把刀磨快!!当然,除了Maven还有其他的选择Gradle(推荐), Ivy….
后面将会有介绍几篇MapReduce开发的文章,都要依赖于本文中Maven的构建的MapReduce环境。
目录
- Maven介绍
- Maven安装(win)
- Hadoop开发环境介绍
- 用Maven构建Hadoop环境
- MapReduce程序开发
- 模板项目上传github
1. Maven介绍
Apache Maven,是一个Java的项目管理及自动构建工具,由Apache软件基金会所提供。基于项目对象模型(缩写:POM)概念,Maven利用一个*信息片断能管理一个项目的构建、报告和文档等步骤。曾是Jakarta项目的子项目,现为独立Apache项目。
maven的开发者在他们开发网站上指出,maven的目标是要使得项目的构建更加容易,它把编译、打包、测试、发布等开发过程中的不同环节有机的串联了起来,并产生一致的、高质量的项目信息,使得项目成员能够及时地得到反馈。maven有效地支持了测试优先、持续集成,体现了鼓励沟通,及时反馈的软件开发理念。如果说Ant的复用是建立在”拷贝–粘贴”的基础上的,那么Maven通过插件的机制实现了项目构建逻辑的真正复用。
2. Maven安装(win)
下载Maven:http://maven.apache.org/download.cgi
下载最新的xxx-bin.zip文件,在win上解压到 D:\toolkit\maven3
并把maven/bin目录设置在环境变量PATH:
然后,打开命令行输入mvn,我们会看到mvn命令的运行效果
~ C:\Users\Administrator>mvn
[INFO] Scanning for projects…
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.086s
[INFO] Finished at: Mon Sep 30 18:26:58 CST 2013
[INFO] Final Memory: 2M/179M
[INFO] ------------------------------------------------------------------------
[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format : or :[:]:. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-class
es, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/NoGoalSpecifiedException
安装Eclipse的Maven插件:Maven Integration for Eclipse
Maven的Eclipse插件配置
3. Hadoop开发环境介绍
如上图所示,我们可以选择在win中开发,也可以在linux中开发,本地启动Hadoop或者远程调用Hadoop,标配的工具都是Maven和Eclipse。
Hadoop集群系统环境:
Linux: Ubuntu 12.04.2 LTS 64bit Server
Java: 1.6.0_29
Hadoop: hadoop-1.0.3,单节点,IP:192.168.1.210
4. 用Maven构建Hadoop环境
- 用Maven创建一个标准化的Java项目
- 导入项目到eclipse
- 增加hadoop依赖,修改pom.xml
- 下载依赖
- 从Hadoop集群环境下载hadoop配置文件
- 配置本地host
1). 用Maven创建一个标准化的Java项目
~ D:\workspace\java>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 [INFO] Scanning for projects… [INFO] [INFO]
------------------------------------------------------------------------ [INFO] Building Maven Stub Project (No POM) 1 [INFO]
------------------------------------------------------------------------ [INFO] [INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @
standalone-pom >>> [INFO] [INFO] <<<
maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom <<<
[INFO] [INFO] — maven-archetype-plugin:2.2:generate (default-cli) @
standalone-pom — [INFO] Generating project in Batch mode [INFO] No
archetype defined. Using maven-archetype-quickstart
(org.apache.maven.archetypes:maven-archetype-quickstart:1. 0)
Downloading:
http://repo.maven.apache.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archet
ype-quickstart-1.0.jar Downloaded:
http://repo.maven.apache.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archety
pe-quickstart-1.0.jar (5 KB at 4.3 KB/sec) Downloading:
http://repo.maven.apache.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archet
ype-quickstart-1.0.pom Downloaded:
http://repo.maven.apache.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archety
pe-quickstart-1.0.pom (703 B at 1.6 KB/sec) [INFO]
---------------------------------------------------------------------------- [INFO] Using following parameters for creating project from Old (1.x)
Archetype: maven-archetype-quickstart:1.0 [INFO]
---------------------------------------------------------------------------- [INFO] Parameter: groupId, Value: org.conan.myhadoop.mr [INFO]
Parameter: packageName, Value: org.conan.myhadoop.mr [INFO] Parameter:
package, Value: org.conan.myhadoop.mr [INFO] Parameter: artifactId,
Value: myHadoop [INFO] Parameter: basedir, Value: D:\workspace\java
[INFO] Parameter: version, Value: 1.0-SNAPSHOT [INFO] project created
from Old (1.x) Archetype in dir: D:\workspace\java\myHadoop [INFO]
------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO]
------------------------------------------------------------------------ [INFO] Total time: 8.896s [INFO] Finished at: Sun Sep 29 20:57:07 CST
2013 [INFO] Final Memory: 9M/179M [INFO]
进入项目,执行mvn命令
~ D:\workspace\java>cd myHadoop ~ D:\workspace\java\myHadoop>mvn clean
install [INFO] [INFO] — maven-jar-plugin:2.3.2:jar (default-jar) @
myHadoop — [INFO] Building jar:
D:\workspace\java\myHadoop\target\myHadoop-1.0-SNAPSHOT.jar [INFO]
[INFO] — maven-install-plugin:2.3.1:install (default-install) @
myHadoop — [INFO] Installing
D:\workspace\java\myHadoop\target\myHadoop-1.0-SNAPSHOT.jar to
C:\Users\Administrator.m2\repository\o
rg\conan\myhadoop\mr\myHadoop\1.0-SNAPSHOT\myHadoop-1.0-SNAPSHOT.jar
[INFO] Installing D:\workspace\java\myHadoop\pom.xml to
C:\Users\Administrator.m2\repository\org\conan\myhadoop\mr\myHa
doop\1.0-SNAPSHOT\myHadoop-1.0-SNAPSHOT.pom [INFO]
------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO]
------------------------------------------------------------------------ [INFO] Total time: 4.348s [INFO] Finished at: Sun Sep 29 20:58:43 CST
2013 [INFO] Final Memory: 11M/179M [INFO]
2). 导入项目到eclipse
我们创建好了一个基本的maven项目,然后导入到eclipse中。 这里我们最好已安装好了Maven的插件。
3). 增加hadoop依赖
- 这里我使用hadoop-1.0.3版本,修改文件:pom.xml
- vi pom.xml
4.0.0
org.conan.myhadoop.mr
myHadoop jar
1.0-SNAPSHOT myHadoop
http://maven.apache.org
org.apache.hadoop
hadoop-core 1.0.3junit junit
4.4 test
4). 下载依赖
- 下载依赖:
- mvn clean install
在eclipse中刷新项目:
项目的依赖程序,被自动加载的库路径下面。
5). 从Hadoop集群环境下载hadoop配置文件
core-site.xml
hdfs-site.xml
mapred-site.xml
查看core-site.xml
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl"href=“configuration.xsl”?>
fs.default.name
hdfs://master:9000
hadoop.tmp.dir /home/conan/hadoop/tmp
io.sort.mb 256
查看hdfs-site.xml
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl"href=“configuration.xsl”?>
dfs.data.dir
/home/conan/hadoop/data
dfs.replication 1
dfs.permissions false
查看mapred-site.xml
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl"href=“configuration.xsl”?>
mapred.job.tracker
hdfs://master:9001
保存在src/main/resources/hadoop目录下面
删除原自动生成的文件:App.java和AppTest.java
6).配置本地host,增加master的域名指向
~ vi c:/Windows/System32/drivers/etc/hosts
192.168.1.210 master
6. MapReduce程序开发
编写一个简单的MapReduce程序,实现wordcount功能。
新一个Java文件:WordCount.java
package org.conan.myhadoop.mr;
import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
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.Reducer;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.mapred.TextInputFormat;
import org.apache.hadoop.mapred.TextOutputFormat;
public class WordCount {
public static class WordCountMapper extends MapReduceBase implements Mapper<Object, Text, Text, IntWritable> {
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
@Override
public void map(Object key, Text value, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
output.collect(word, one);
}
}
}
public static class WordCountReducer extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();
@Override
public void reduce(Text key, Iterator values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {
int sum = 0;
while (values.hasNext()) {
sum += values.next().get();
}
result.set(sum);
output.collect(key, result);
}
}
public static void main(String[] args) throws Exception {
String input = "hdfs://192.168.1.210:9000/user/hdfs/o_t_account";
String output = "hdfs://192.168.1.210:9000/user/hdfs/o_t_account/result";
JobConf conf = new JobConf(WordCount.class);
conf.setJobName("WordCount");
conf.addResource("classpath:/hadoop/core-site.xml");
conf.addResource("classpath:/hadoop/hdfs-site.xml");
conf.addResource("classpath:/hadoop/mapred-site.xml");
conf.setOutputKeyClass(Text.class);
conf.setOutputValueClass(IntWritable.class);
conf.setMapperClass(WordCountMapper.class);
conf.setCombinerClass(WordCountReducer.class);
conf.setReducerClass(WordCountReducer.class);
conf.setInputFormat(TextInputFormat.class);
conf.setOutputFormat(TextOutputFormat.class);
FileInputFormat.setInputPaths(conf, new Path(input));
FileOutputFormat.setOutputPath(conf, new Path(output));
JobClient.runJob(conf);
System.exit(0);
}
}
启动Java APP.
控制台错误
2013-9-30 19:25:02 org.apache.hadoop.util.NativeCodeLoader 警告: Unable
to load native-hadoop library for your platform… using builtin-java
classes where applicable 2013-9-30 19:25:02
org.apache.hadoop.security.UserGroupInformation doAs 严重:
PriviledgedActionException as:Administrator cause:java.io.IOException:
Failed to set permissions of path:
\tmp\hadoop-Administrator\mapred\staging\Administrator1702422322.staging
to 0700 Exception in thread “main” java.io.IOException: Failed to set
permissions of path:
\tmp\hadoop-Administrator\mapred\staging\Administrator1702422322.staging
to 0700 at
org.apache.hadoop.fs.FileUtil.checkReturnValue(FileUtil.java:689) at
org.apache.hadoop.fs.FileUtil.setPermission(FileUtil.java:662) at
org.apache.hadoop.fs.RawLocalFileSystem.setPermission(RawLocalFileSystem.java:509)
at
org.apache.hadoop.fs.RawLocalFileSystem.mkdirs(RawLocalFileSystem.java:344)
at
org.apache.hadoop.fs.FilterFileSystem.mkdirs(FilterFileSystem.java:189)
at
org.apache.hadoop.mapreduce.JobSubmissionFiles.getStagingDir(JobSubmissionFiles.java:116)
at org.apache.hadoop.mapred.JobClient$2.run(JobClient.java:856) at
org.apache.hadoop.mapred.JobClient$2.run(JobClient.java:850) at
java.security.AccessController.doPrivileged(Native Method) at
javax.security.auth.Subject.doAs(Subject.java:396) at
org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1121)
at
org.apache.hadoop.mapred.JobClient.submitJobInternal(JobClient.java:850)
at org.apache.hadoop.mapred.JobClient.submitJob(JobClient.java:824)
at org.apache.hadoop.mapred.JobClient.runJob(JobClient.java:1261) at
org.conan.myhadoop.mr.WordCount.main(WordCount.java:78)
这个错误是win中开发特有的错误,文件权限问题,在Linux下可以正常运行。
解决方法是,修改/hadoop-1.0.3/src/core/org/apache/hadoop/fs/FileUtil.java文件
688-692行注释,然后重新编译源代码,重新打一个hadoop.jar的包。
685 private static void checkReturnValue(boolean rv, File p, 686
FsPermission permission 687 )
throws IOException { 688 /if (!rv) { 689 throw new
IOException(“Failed to set permissions of path: " + p + 690
" to " + 691 String.format(”%04o",
permission.toShort())); 692 }/ 693 }
我这里自己打了一个hadoop-core-1.0.3.jar包,放到了lib下面。
我们还要替换maven中的hadoop类库。
~ cp lib/hadoop-core-1.0.3.jar
C:\Users\Administrator.m2\repository\org\apache\hadoop\hadoop-core\1.0.3\hadoop-core-1.0.3.jar
再次启动Java APP,控制台输出:
2013-9-30 19:50:49 org.apache.hadoop.util.NativeCodeLoader
警告: Unable to load native-hadoop library for your platform… using builtin-java classes where applicable
2013-9-30 19:50:49 org.apache.hadoop.mapred.JobClient copyAndConfigureFiles
警告: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
2013-9-30 19:50:49 org.apache.hadoop.mapred.JobClient copyAndConfigureFiles
警告: No job jar file set. User classes may not be found. See JobConf(Class) or JobConf#setJar(String).
2013-9-30 19:50:49 org.apache.hadoop.io.compress.snappy.LoadSnappy
警告: Snappy native library not loaded
2013-9-30 19:50:49 org.apache.hadoop.mapred.FileInputFormat listStatus
信息: Total input paths to process : 4
2013-9-30 19:50:50 org.apache.hadoop.mapred.JobClient monitorAndPrintJob
信息: Running job: job_local_0001
2013-9-30 19:50:50 org.apache.hadoop.mapred.Task initialize
信息: Using ResourceCalculatorPlugin : null
2013-9-30 19:50:50 org.apache.hadoop.mapred.MapTask runOldMapper
信息: numReduceTasks: 1
2013-9-30 19:50:50 org.apache.hadoop.mapred.MapTaskMapOutputBuffer
信息: data buffer = 79691776/99614720
2013-9-30 19:50:50 org.apache.hadoop.mapred.MapTaskMapOutputBuffer flush
信息: Starting flush of map output
2013-9-30 19:50:50 org.apache.hadoop.mapred.MapTaskKaTeX parse error: Double subscript at position 134: …pt_local_0001_m_̲000000_0 is don…Job statusUpdate
信息: hdfs://192.168.1.210:9000/user/hdfs/o_t_account/part-m-00003:0+119
2013-9-30 19:50:53 org.apache.hadoop.mapred.Task sendDone
信息: Task ‘attempt_local_0001_m_000000_0’ done.
2013-9-30 19:50:53 org.apache.hadoop.mapred.Task initialize
信息: Using ResourceCalculatorPlugin : null
2013-9-30 19:50:53 org.apache.hadoop.mapred.MapTask runOldMapper
信息: numReduceTasks: 1
2013-9-30 19:50:53 org.apache.hadoop.mapred.MapTaskMapOutputBuffer
信息: data buffer = 79691776/99614720
2013-9-30 19:50:53 org.apache.hadoop.mapred.MapTaskMapOutputBuffer flush
信息: Starting flush of map output
2013-9-30 19:50:53 org.apache.hadoop.mapred.MapTaskKaTeX parse error: Double subscript at position 134: …pt_local_0001_m_̲000001_0 is don…Job statusUpdate
信息: hdfs://192.168.1.210:9000/user/hdfs/o_t_account/part-m-00000:0+113
2013-9-30 19:50:56 org.apache.hadoop.mapred.Task sendDone
信息: Task ‘attempt_local_0001_m_000001_0’ done.
2013-9-30 19:50:56 org.apache.hadoop.mapred.Task initialize
信息: Using ResourceCalculatorPlugin : null
2013-9-30 19:50:56 org.apache.hadoop.mapred.MapTask runOldMapper
信息: numReduceTasks: 1
2013-9-30 19:50:56 org.apache.hadoop.mapred.MapTaskMapOutputBuffer
信息: data buffer = 79691776/99614720
2013-9-30 19:50:56 org.apache.hadoop.mapred.MapTaskMapOutputBuffer flush
信息: Starting flush of map output
2013-9-30 19:50:56 org.apache.hadoop.mapred.MapTaskKaTeX parse error: Double subscript at position 134: …pt_local_0001_m_̲000002_0 is don…Job statusUpdate
信息: hdfs://192.168.1.210:9000/user/hdfs/o_t_account/part-m-00001:0+110
2013-9-30 19:50:59 org.apache.hadoop.mapred.LocalJobRunnerKaTeX parse error: Double subscript at position 61: …0/user/hdfs/o_t_̲account/part-m-…MapOutputBuffer
信息: io.sort.mb = 100
2013-9-30 19:50:59 org.apache.hadoop.mapred.MapTaskMapOutputBuffer
信息: record buffer = 262144/327680
2013-9-30 19:50:59 org.apache.hadoop.mapred.MapTaskMapOutputBuffer sortAndSpill
信息: Finished spill 0
2013-9-30 19:50:59 org.apache.hadoop.mapred.Task done
信息: Task:attempt_local_0001_m_000003_0 is done. And is in the process of commiting
2013-9-30 19:51:02 org.apache.hadoop.mapred.LocalJobRunnerKaTeX parse error: Double subscript at position 61: …0/user/hdfs/o_t_̲account/part-m-…Job statusUpdate
信息:
2013-9-30 19:51:02 org.apache.hadoop.mapred.MergerMergeQueue merge
信息: Down to the last merge-pass, with 4 segments left of total size: 442 bytes
2013-9-30 19:51:02 org.apache.hadoop.mapred.LocalJobRunnerKaTeX parse error: Double subscript at position 106: …pt_local_0001_r_̲000000_0 is don…Job statusUpdate
信息:
2013-9-30 19:51:02 org.apache.hadoop.mapred.Task commit
信息: Task attempt_local_0001_r_000000_0 is allowed to commit now
2013-9-30 19:51:02 org.apache.hadoop.mapred.FileOutputCommitter commitTask
信息: Saved output of task ‘attempt_local_0001_r_000000_0’ to hdfs://192.168.1.210:9000/user/hdfs/o_t_account/result
2013-9-30 19:51:05 org.apache.hadoop.mapred.LocalJobRunner$Job statusUpdate
信息: reduce > reduce
2013-9-30 19:51:05 org.apache.hadoop.mapred.Task sendDone
信息: Task ‘attempt_local_0001_r_000000_0’ done.
2013-9-30 19:51:06 org.apache.hadoop.mapred.JobClient monitorAndPrintJob
信息: map 100% reduce 100%
2013-9-30 19:51:06 org.apache.hadoop.mapred.JobClient monitorAndPrintJob
信息: Job complete: job_local_0001
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Counters: 20
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: File Input Format Counters
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Bytes Read=421
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: File Output Format Counters
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Bytes Written=348
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: FileSystemCounters
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: FILE_BYTES_READ=7377
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: HDFS_BYTES_READ=1535
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: FILE_BYTES_WRITTEN=209510
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: HDFS_BYTES_WRITTEN=348
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Map-Reduce Framework
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Map output materialized bytes=458
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Map input records=11
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Reduce shuffle bytes=0
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Spilled Records=30
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Map output bytes=509
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Total committed heap usage (bytes)=1838546944
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Map input bytes=421
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: SPLIT_RAW_BYTES=452
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Combine input records=22
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Reduce input records=15
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Reduce input groups=13
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Combine output records=15
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Reduce output records=13
2013-9-30 19:51:06 org.apache.hadoop.mapred.Counters log
信息: Map output records=22
成功运行了wordcount程序,通过命令我们查看输出结果
~ hadoop fs -ls hdfs://192.168.1.210:9000/user/hdfs/o_t_account/result
Found 2 items
-rw-r–r-- 3 Administrator supergroup 0 2013-09-30 19:51 /user/hdfs/o_t_account/result/_SUCCESS
-rw-r–r-- 3 Administrator supergroup 348 2013-09-30 19:51 /user/hdfs/o_t_account/result/part-00000
~ hadoop fs -cat hdfs://192.168.1.210:9000/user/hdfs/o_t_account/result/part-00000
1,[email protected],2013-04-22 1
10,[email protected],2013-04-23 1
11,[email protected],2013-04-23 1
17:21:24.0 5
2,[email protected],2013-04-22 1
20:21:39.0 6
3,[email protected],2013-04-22 1
4,[email protected],2013-04-22 1
5,[email protected],2013-04-22 1
6,[email protected],2013-04-22 1
7,[email protected],2013-04-23 1
8,[email protected],2013-04-23 1
9,[email protected],2013-04-23 1
这样,我们就实现了在win7中的开发,通过Maven构建Hadoop依赖环境,在Eclipse中开发MapReduce的程序,然后运行JavaAPP。Hadoop应用会自动把我们的MR程序打成jar包,再上传的远程的hadoop环境中运行,返回日志在Eclipse控制台输出。
7. 模板项目上传github
https://github.com/bsspirit/maven_hadoop_template
大家可以下载这个项目,做为开发的起点。
~ git clone https://github.com/bsspirit/maven_hadoop_template.git
我们完成第一步,下面就将正式进入MapReduce开发实践。
二、Ambari——大数据平台的搭建利器
Ambari 是什么
Ambari 跟 Hadoop 等开源软件一样,也是 Apache Software Foundation 中的一个项目,并且是*项目。目前最新的发布版本是 2.0.1,未来不久将发布 2.1 版本。就 Ambari 的作用来说,就是创建、管理、监视 Hadoop 的集群,但是这里的 Hadoop 是广义,指的是 Hadoop 整个生态圈(例如 Hive,Hbase,Sqoop,Zookeeper 等),而并不仅是特指 Hadoop。用一句话来说,Ambari 就是为了让 Hadoop 以及相关的大数据软件更容易使用的一个工具。
说到这里,大家就应该明白什么人最需要 Ambari 了。那些苦苦花费好几天去安装、调试 Hadoop 的初学者是最能体会到 Ambari 的方便之处的。而且,Ambari 现在所支持的平台组件也越来越多,例如流行的 Spark,Storm 等计算框架,以及资源调度平台 YARN 等,我们都能轻松地通过 Ambari 来进行部署。
Ambari 自身也是一个分布式架构的软件,主要由两部分组成:Ambari Server 和 Ambari Agent。简单来说,用户通过 Ambari Server 通知 Ambari Agent 安装对应的软件;Agent 会定时地发送各个机器每个软件模块的状态给 Ambari Server,最终这些状态信息会呈现在 Ambari 的 GUI,方便用户了解到集群的各种状态,并进行相应的维护。详细的操作和介绍会在后续章节介绍。
Ambari 的安装
安装准备
关于 Ambari 的安装,目前网上能找到两个发行版,一个是 Apache 的 Ambari,另一个是 Hortonworks 的,两者区别不大。这里就以 Apache 的 Ambari 2.0.1 作为示例。本文使用三台 Redhat 6.6 作为安装环境(目前测试验证结果为 Ambari 在 Redhat 6.6 的版本上运行比较稳定),三台机器分别为 zwshen37.example.com、zwshen38.example.com、zwshen39.example.com。zwshen37 计划安装为 Ambari 的 Server,另外两台为 Ambari Agent。
安装 Ambari 最方便的方式就是使用公共的库源(public repository)。有兴趣的朋友可以自己研究一下搭建一个本地库(local repository)进行安装。这个不是重点,所以不在此赘述。在进行具体的安装之前,需要做几个准备工作。
- SSH 的无密码登录;
Ambari 的 Server 会 SSH 到 Agent 的机器,拷贝并执行一些命令。因此我们需要配置 Ambari Server 到 Agent 的 SSH 无密码登录。在这个例子里,zwshen37 可以 SSH 无密码登录 zwshen38 和 zwshen39。 - 确保 Yum 可以正常工作;
通过公共库(public repository),安装 Hadoop 这些软件,背后其实就是应用 Yum 在安装公共库里面的 rpm 包。所以这里需要您的机器都能访问 Internet。 - 确保 home 目录的写权限。
Ambari 会创建一些 OS 用户。 - 确保机器的 Python 版本大于或等于 2.6.(Redhat6.6,默认就是 2.6 的)。
以上的准备工作完成后,便可以真正的开始安装 Ambari 了。
安装过程
首先需要获取 Ambari 的公共库文件(public repository)。登录到 Linux 主机并执行下面的命令(也可以自己手工下载):
1 |
wget < a href = "http://public-repo-1.hortonworks.com/ambari/centos6/2.x/updates/2.0.1/ambari.repo" >< code >http://public-repo-1.hortonworks.com/ambari/centos6/2.x/updates/2.0.1/ambari.repo</ code ></ a >
|
将下载的 ambari.repo 文件拷贝到 Linux 的系统目录/etc/yum.repos.d/。拷贝完后,我们需要获取该公共库的所有的源文件列表。依次执行以下命令。
1
2
|
yum clean all yum list|grep ambari |
如图 1 所示:
图 1. 获取公共库源文件列表
如果可以看到 Ambari 的对应版本的安装包列表,说明公共库已配置成功。然后就可以安装 Ambari 的 package 了。执行下面的命令安装 Ambari Server 到该机器。
1 |
yum install ambari-server |
待安装完成后,便需要对 Ambari Server 做一个简单的配置。执行下面的命令。
1 |
amari-server setup |
在这个交互式的设置中,采用默认配置即可。Ambari 会使用 Postgres 数据库,默认会安装并使用 Oracle 的 JDK。默认设置了 Ambari GUI 的登录用户为 admin/admin。并且指定 Ambari Server 的运行用户为 root。
简单的 setup 配置完成后。就可以启动 Ambari 了。运行下面的命令。
1 |
ambari-server start |
当成功启动 Ambari Server 之后,便可以从浏览器登录,默认的端口为 8080。以本文环境为例,在浏览器的地址栏输入 http://zwshen37.example.com:8080,登录密码为 admin/admin。登入 Ambari 之后的页面如下图。
图 2. Ambari 的 welcome 页面
至此,Ambari Server 就安装完成了。
部署一个 Hadoop2.x 集群
到这一节,我们将可以真正地体验到 Ambari 的用武之地,以及它所能带来的方便之处。
登录 Ambari 之后,点击按钮“Launch Install Wizard”,就可以开始创建属于自己的大数据平台。
第一步,命名集群的名字。本环境为 bigdata。
第二步,选择一个 Stack,这个 Stack 相当于一个 Hadoop 生态圈软件的集合。Stack 的版本越高,里面的软件版本也就越高。这里我们选择 HDP2.2,里面的对应的 Hadoop 版本为 2.6.x。
第三步,指定 Agent 机器(如果配置了域,必须包含完整域名,例如本文环境的域为 example.com),这些机器会被安装 Hadoop 等软件包。还记得在安装章节中提到的 SSH 无密码登陆吗,这里需要指定当时在 Ambari Server 机器生成的私钥(ssh-****** 生成的,公钥已经拷贝到 Ambari Agent 的机器,具体的 SSH 无密码登录配置,可以在网上很容易找到配置方法,不在此赘述)。另外不要选择“Perform manual registration on hosts and do not use SSH“。因为我们需要 Ambari Server 自动去安装 Ambari Agent。具体参见下图示例。
图 3. 安装配置页面
第四步,Ambari Server 会自动安装 Ambari Agent 到刚才指定的机器列表。安装完成后,Agent 会向 Ambari Server 注册。成功注册后,就可以继续 Next 到下一步。
第五步,这里我们终于看到跟 Hadoop 有关的名词了。在这一步,我们需要选择要安装的软件名称。本文环境选择了 HDFS,YARN + MapReduce2,Zoopkeeper,Storm 以及 Spark。选的越多,就会需要越多的机器内存。选择之后就可以继续下一步了。这里需要注意某些 Service 是有依赖关系的。如果您选了一个需要依赖其他 Service 的一个 Service,Ambari 会提醒安装对应依赖的 Service。参见下图。
图 4. Service 选择页面
第六步和第七步,分别是选择安装软件所指定的 Master 机器和 Slave 机器,以及 Client 机器。这里使用默认选择即可(真正在生产环境中,需要根据具体的机器配置选择)。
第八步,就是 Service 的配置。绝大部分配置已经有默认值,不需要修改。初学者,如果不需要进行调优是可以直接使用默认配置的。有些 Service 会有一些必须的手工配置项,则必须手动输入,才可以下一步。本文环境直接使用默认配置。
第九步,Ambari 会总结一个安装列表,供用户审阅。这里没问题,就直接下一步。
第十步,Ambari 会开始安装选择的 Service 到 Ambari Agent 的机器(如下图)。这里可能需要等好一会,因为都是在线安装。安装完成之后,Ambari 就会启动这些 Service。
图 5. Service 的安装进度
安装完成之后,就可以查看 Ambari 的 Dashboard 了。例如下图。
图 6. Ambari 的 Dashboard 页面
至此,您专属的 bigdata 集群已经安装完成。
利用 Ambari 管理 Hadoop 集群
在上一章节中,我们已经体验到 Ambari 为 Hadoop 生态圈的安装提供的便利。这已经省去了很多的人力成本。尤其是对大数据圈子的测试人员来说,自动化就容易了很多。下面我们看看如何通过 Ambari 管理 Hadoop 的集群。
Service Level Action(服务级别的操作)
首先我们进到 Ambari 的 GUI 页面,并查看 Dashboard。在左侧的 Service 列表中,我们可以点击任何一个您想要操作的 Service。以 MapReduce2 为例(Hadoop 这里的版本为 2.6.x,也就是 YARN+HDFS+MapReduce),当点击 MapReduce2 后,就会看到该 Service 的相关信息,如下图。
图 7. MapRduce2 的 Service 页面
中间部分是 Service 的模块(Component)信息,也就是该 Service 有哪些模块及其数目。右上角有个 Service Action 的按钮,当点击该按钮后就可以看到很多 Service 的控制命令。也就是通过这些 Service Action 命令,对 Service 进行管理的。
可能有的人会说,装完 Hadoop 的集群后,并不知道这个集群是不是可用。这时候我们就可以运行一个“Run Service Check”。点击这个命令后,就会出现下图的进度显示。
图 8. MapReduce Service Check
其实这里就是通过运行一个经典的 MapReduce Wordcount 实例,来检查 MapReduce 是不是正常。对于 Service Action 里面的 Start、Stop 的含义就是,启停整个集群所有该 Service 的模块(也就是 Service level)。当执行进度页面弹出来的时候,我们可以点击 Operations 的名字,进而查看每个机器的进度和运行 log。如下图 Stop 的操作。
图 9. 命令执行进度 1
图 10. 命令执行进度 2
维护模式(Maintenance Mode)以及如何添加一个自定义的命令到 Service Action,我会在后续的连载中进行介绍。
Host Level Action(机器级别的操作)
首先,我们回到 Ambari 的 Dashboard 页面。页面最上面中间的地方有个 Hosts,点击这个标签,我们就可以看到 Ambari 所管理的机器列表。如下图。
图 11. Ambari 的机器列表
图片中红色的数字是警告信息(Ambari Alert),这里我们先略过它,后续文章再做介绍。先看左上角的 Actions,点击这个按钮,就可以看到 Host level Action 的选项了,其实和 Service Level 是类似的,只是执行的范围不一样。如下图。当用户选择 All Hosts -> Hosts -> Start All Components,Ambari 就会将所有 Service 的所有模块启动。
图 12. 启动所有 Service 的所有模块
如果用户选择 All Hosts-> DataNodes -> Stop,Ambari 就会把所有机器的 DataNode 这个模块关闭。如下图。
图 13. 关闭所有的 DataNode 模块
Component Level Action(模块级别的操作)
上面的图中,我们可以看到 Decommisson、Recommission。这些命令其实是自定义的模块级别的操作(Component Level Action)。不过上图中命令一旦执行,就是对多个机器的同个模块执行。
我们现在尝试只对单个机器的一个模块(Component)执行。首先我们回到 Hosts 的页面。这时候点击机器名,我们就会进入到该机器的 Component 页面。如下图。
图 14. Component 页面
这时候只要点击每个 Component(模块)后面的按钮,就可以看到该模块的操作命令了。例如,我们可以停掉这台机器的 DataNode 模块。
图 15. 停止 DataNode 模块 1
图 16. 停止 DataNode 模块 2
关于如何给一个模块添加自定义的命令,也会在后续的连载中做介绍。
这一章节中,主要介绍了如何通过三种级别的 Action(操作)管理 Hadoop 的集群。在 Ambari 中已经加入了很多自定义的 Action 去做一些特殊的操作。如果对 Hadoop 生态圈的软件足够熟悉,就可以尝试更多的 Action。可能有的人会问,Ambari 可不可以扩容集群。答案当然是可以的。Ambari 可以给自身的集群添加机器(也就是添加 Ambari Agent),然后将 Service 的模块安装在新的机器,也可以把某些模块安装到已有的其他的机器。篇幅有限,将在后续的连载中介绍更多的内容。
Ambari 的架构和工作原理
Ambari 基本的架构和工作原理如下图 17 所示。
图 17. Ambari 的基本架构
Ambari Server 会读取 Stack 和 Service 的配置文件。当用 Ambari 创建集群的时候,Ambari Server 传送 Stack 和 Service 的配置文件以及 Service 生命周期的控制脚本到 Ambari Agent。Agent 拿到配置文件后,会下载安装公共源里软件包(Redhat,就是使用 yum 服务)。安装完成后,Ambari Server 会通知 Agent 去启动 Service。之后 Ambari Server 会定期发送命令到 Agent 检查 Service 的状态,Agent 上报给 Server,并呈现在 Ambari 的 GUI 上。
Ambari Server 支持 Rest API,这样可以很容易的扩展和定制化 Ambari。甚至于不用登陆 Ambari 的 GUI,只需要在命令行通过 curl 就可以控制 Ambari,以及控制 Hadoop 的 cluster。具体的 API 可以参见 Apache Ambari 的官方网页 API reference。
对于安全方面要求比较苛刻的环境来说,Ambari 可以支持 Kerberos 认证的 Hadoop 集群。
扩展 Ambari 管理一个自定义的 Service
首先,我们需要规划自定义的 Service 属于哪个 Stack(当然 Stack 也是可以自定义的)。这里为了快速创建一个新的 Service,而且我们已经安装了 HDP 2.2 的 Stack,所以就将自定义的 Service 放在 HDP 2.2 之下。
第一步,首先在 Ambari Service 机器上找到 HDP 2.2 Stack 的目录,如下图所示。
图 18. HDP 2.2 的目录
第二步,需要创建一个 Service 目录,我们这里用“SAMPLE”作为目录名。并在 SAMPLE 底下创建 metainfo.xml。示例代码如下。主要解释下 xml 代码中的两个字段 category 和 cardinality。category 指定了该模块(Component)的类别,可以是 MASTER、SLAVE、CLIENT。Cardinality 指的是所要安装的机器数,可以是固定数字 1,可以是一个范围比如 1-2,也可以是 1+,或者 ALL。如果是一个范围的时候,安装的时候会让用户选择机器。另外这里有关 Service 和 Component 的 name 配置要用大写,小写有时候会有问题。Displayname 可以随意设置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
<? xml version = "1.0" ?>
< metainfo >
< schemaVersion >2.0</ schemaVersion >
< services >
< service >
< name >SAMPLE</ name >
< displayName >My Sample</ displayName >
< comment >My v1 Sample</ comment >
< version >1.0</ version >
< components >
< component >
< name >MYMASTER</ name >
< displayName >My Master</ displayName >
< category >MASTER</ category >
< cardinality >1</ cardinality >
< commandScript >
<script> scripts/master.py </script>
<scriptType> PYTHON</ scriptType >
< timeout >5000</ timeout >
</ commandScript >
</ component >
< component >
< name >MYSALVE</ name >
< displayName >My Slave</ displayName >
< category >SLAVE</ category >
< cardinality >1+</ cardinality >
< commandScript >
< script >scripts/slave.py </script>
< scriptType >PYTHON</ scriptType >
< timeout >5000</ timeout >
</ commandScript >
</ component >
</ components >
< osSpecifics >
< osSpecific >
< osFamily >any</ osFamily >
</ osSpecific >
</ osSpecifics >
</ service >
</ services >
</ metainfo >
|
第三步,需要创建 Service 的控制脚本。这里我们需要在 SAMPLE 底下创建一个 package 目录,然后在 package 底下创建目录 scripts ,进而创建 master.py 和 slave.py。这里需要保证脚本路径和上一步中 metainfo.xml 中的配置路径是一致的。这两个 Python 脚本是用来控制 Master 和 Slave 模块的生命周期。脚本中函数的含义也如其名字一样:install 就是安装调用的接口;start、stop 分别就是启停的调用;Status 是定期检查 component 状态的调用;Configure 是安装完成配置该模块的调用。示例目录结构如下图。
图 19. Sample Service 的目录结构
Python 脚本的示例代码:
Master.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
import sys, os from resource_management import * from resource_management.core.exceptions import ComponentIsNotRunning from resource_management.core.environment import Environment from resource_management.core.logger import Logger class Master(Script): def install(self, env):
print "Install My Master"
def configure(self, env):
print "Configure My Master"
def start(self, env):
print "Start My Master"
def stop(self, env):
print "Stop My Master"
def status(self, env):
print "Status..."
if __name__ == "__main__": Master().execute()
|
Slave.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
import sys, os from resource_management import * from resource_management.core.exceptions import ComponentIsNotRunning from resource_management.core.environment import Environment from resource_management.core.logger import Logger class Slave(Script): def install(self, env):
print "Install My Slave"
def configure(self, env):
print "Configure My Slave"
def start(self, env):
print "Start My Slave"
def stop(self, env):
print "Stop My Slave"
def status(self, env):
print "Status..."
if __name__ == "__main__": Slave().execute()
|
第四步,需要重启 Ambari Server。因为 Ambari Server 只有在重启的时候才会读取 Service 和 Stack 的配置。命令行执行:
1 |
ambari-server restart |
第五步,登录 Ambari 的 GUI,点击左下角的 Action,选择 Add Service。如下图:
图 20. Add Service 按钮
这时候就可以看到我们自定义的 Service:SAMPLE。如下图:
图 21. Sample Service 列表
选择左侧 My Sample 后,就可以一路 Next 了,这个过程其实和我们在搭建 Hadoop2.x 集群的时候是类似的。由于这个 Service 没有真的安装包,所以安装过程会非常的快,启动命令也没有真正的逻辑,所以启动过程也是很快的。等最后点击完 Complete,整个安装过程也就结束了。再回到 Ambari 的 Dashboard 的时候,我们就可以看到这个 My Sample 了,如下图:
图 22. My Sample 的 Service 页面
到此就可以和第四节中管理 Hadoop 集群一样管理我们的 My Sample。例如下图,Stop 我们的 My Sample。
图 23. Stop Sample 页面 1
图 24. Stop Sample 页面 2
图 25. Stop Sample 页面 3
进阶的篇幅中,将会探讨如何给我们的 My Sample 自定义一些 Actions,以及 Action 之间的依赖关系如何定义。篇幅有限,这里就先到此为止。希望以上的介绍能够燃起大家对 Ambari 的热情。
总结
大数据与云计算可谓是如今数据中心中最火的两项技术领域,几乎所有的 IT 服务商都想在这两项技术中有所建树。相信 Ambari 可以帮助一些 Hadoop 的初学者。长远看来,大数据的发展离不开云计算,云计算中 IaaS 可谓已经很成熟,并且价格低廉。这时候许多公司将目光聚集在了 PaaS。大数据的流行更是加速了相关 PaaS 产品的发展,而 Ambari 的出现必然可以拉近 IaaS 和 PaaS 的距离。也就是说有了 Ambari,或许再加上 Docker,那么快速从 IaaS 演进到 PaaS 就显得不是那么困难了。
当然这里 Ambari 要跟 IaaS 更好的切合,还有个对手那就是 Sahara。它是另一个土生土长的 OpenStack 的子项目,其目的也是为了在 Openstack 上面快速搭建 Hadoop 等集群。期望着这些项目能够快速成长,将来对大家都有所帮助。
上一篇: hadoop_ssh简介
下一篇: hadoop_rpc简介