hadoop进行分布式并行编程第三部分.docx
《hadoop进行分布式并行编程第三部分.docx》由会员分享,可在线阅读,更多相关《hadoop进行分布式并行编程第三部分.docx(18页珍藏版)》请在冰豆网上搜索。
hadoop进行分布式并行编程第三部分
用Hadoop进行分布式并行编程,第3部分
部署到分布式环境
曹羽中 (caoyuz@),软件工程师,IBM中国开发中心
简介:
Hadoop是一个实现了MapReduce计算模型的开源分布式并行编程框架,借助于Hadoop,程序员可以轻松地编写分布式并行程序,将其运行于计算机集群上,完成海量数据的计算。
在本文中,详细介绍了如何部署 Hadoop分布式运行环境,如何让程序分布式运行于多台普通的计算机上,如何使用IBMMapReduceTools轻松地将MapReduce程序部署到Hadoop分布式环境中运行等内容。
标记本文!
发布日期:
2008年7月31日
级别:
初级
访问情况:
4608次浏览
评论:
0 (查看 | 添加评论 -登录)
平均分(7个评分)
为本文评分
一前言
在本系列文章的第一篇:
用Hadoop进行分布式并行编程,第1部分:
基本概念与安装部署中,介绍了MapReduce计算模型,分布式文件系统HDFS,分布式并行计算等的基本原理,并且详细介绍了如何安装Hadoop,如何在单机及伪分布式环境 (在一台单机中用多进程模拟) 运行基于Hadoop的并行程序。
在本系列文章的第二篇:
用Hadoop进行分布式并行编程,第2部分:
程序实例与分析中,介绍了如何针对一个具体的计算任务,基于Hadoop编写MapReduce并行程序。
本文将介绍真实的Hadoop分布式运行环境,包括如何在多台普通的计算机上部署分布式运行环境,如何将MapReduce程序远程部署并运行在这个分布式环境上,并简略介绍了”云计算平台”以及计算能力按需租用服务。
回页首
二准备工作
1.硬件与网络
使用三台机器,机器名分别为homer06,homer07,homer08,均安装RedhatEnterpriseLinux5.0(其它Linux发行版亦可),确保各台机器之间网络畅通,机器名与IP地址之间解析正确,从任一台机器都可以 ping通其它机器的机器名。
如有机器名的解析问题,可通过设置/etc/hosts文件解决,当然更好的解决方法是在你的网络中配置DNS服务器。
此外,需要在三台机器上创建相同的用户帐号,如caoyuz,或直接使用root帐号亦可。
我们将使用homer06作为分布式文件系统HDFS的NameNode 及MapReduce运行过程中的JobTracker结点,我们将homer06 称之为主结点。
其它两台机器(homer07,homer08)作为HDFS的DataNode以及MapReduce运行过程中的TaskTracker结点,这些结点可统称为从结点。
如你需要部署更多的机器,也是很容易的,将新加入的机器作为DataNode 以及TaskTracker结点即可,其配置过程与本文介绍的三台机器的环境类似,此不赘述。
2.SSH配置
在Hadoop分布式环境中,NameNode(主节点)需要通过SSH来启动和停止DataNode(从结点)上的各类进程。
我们需要保证环境中的各台机器均可以通过SSH登录访问,并且NameNode用SSH登录DataNode时,不需要输入密码,这样NameNode才能在后台自如地控制其它结点。
可以将各台机器上的SSH配置为使用无密码公钥认证方式来实现。
现在流行的各类Linux发行版一般都安装了SSH 协议的开源实现OpenSSH,并且已经启动了SSH服务,即这些机器缺省应该就是支持SSH登录的。
如果你的机器缺省不支持SSH,请下载安装OpenSSH。
以下是配置SSH的无密码公钥认证的过程。
首先,在homer06机器上执行命令,如代码清单1所示:
代码清单1
homer06:
$ssh-keygen-trsa
Generatingpublic/privatersakeypair.
Enterfileinwhichtosavethekey(/home/caoyuz/.ssh/id_rsa):
Enterpassphrase(emptyfornopassphrase):
Entersamepassphraseagain:
Youridentificationhasbeensavedin/home/caoyuz/.ssh/id_rsa.
Yourpublickeyhasbeensavedin/home/caoyuz/.ssh/id_rsa.pub.
Thekeyfingerprintis:
2e:
57:
e2:
bf:
fd:
d4:
45:
5c:
a7:
51:
3d:
f1:
51:
3c:
69:
68root@krusty04
这个命令将为homer06上的当前用户caoyuz生成其密钥对,密钥对的保存路径使用缺省的/home/caoyuz/.ssh/id_rsa,要求输入passphrase的时候,直接回车。
这样生成的证书以及公钥将存储在/home/caoyuz/.ssh目录,形成两个文件id_rsa,id_rsa.pub。
然后将id_rsa.pub文件的内容复制到每一台机器(包括本机homer06)的 /home/caoyuz/.ssh/authorized_keys 文件的尾部,如果机器上不存在 /home/caoyuz/.ssh/authorized_keys文件,可以自行创建一个。
请注意id_rsa.pub文件的内容是长长的一行,复制时需注意,不要遗漏字符或混入了多余换行符。
接下来可以做一下SSH连接测试,从homer06分别向homer06,homer07,homer08发起SSH连接请求,确保不需要输入密码就能SSH连接成功。
注意第一次SSH连接时会出现如下提示信息:
Theauthenticityofhost[homer06]can'tbeestablished.Thekeyfingerprintis:
74:
32:
91:
f2:
9c:
dc:
2e:
80:
48:
73:
d4:
53:
ab:
e4:
d3:
1aAreyousureyouwanttocontinueconnecting(yes/no)?
请输入yes,这样OpenSSH会把连接过来的这台主机的信息自动加到/home/caoyuz/.ssh/know_hosts文件中去,第二次再连接时,就不会有这样的提示信息了。
回页首
三安装部署Hadoop
1.安装Hadoop及jre1.5
我们首先在主控结点homer06上安装和配置好Hadoop,安装过程可以参考本系列文章的第一篇。
假定我们把Hadoop安装在/home/caoyuz/hadoop-0.16.0目录中,并且JRE1.5安装在/home/caoyuz/jre目录下。
2.修改conf/hadoop-env.sh文件
在其中设置JAVA_HOME环境变量:
exportJAVA_HOME=”/home/caoyuz/jre”
3.修改conf/hadoop-site.xml文件
在本系列文章的第一篇中,我们通过修改此文件,配置了Hadoop的伪分布式运行模式。
现在,我们同样可以通过配置此文件,配置Hadoop的真实的分布式运行环境。
请参照代码清单2修改conf/hadoop-site.xml:
代码清单2
fs.default.name
:
9000
Thenameofthedefaultfilesystem.Eithertheliteralstring
"local"orahost:
portforDFS.
mapred.job.tracker
:
9001
ThehostandportthattheMapReducejobtrackerrunsat.If
"local",thenjobsarerunin-processasasinglemapandreducetask.
dfs.name.dir
/home/caoyuz/hadoopfs/name
DetermineswhereonthelocalfilesystemtheDFSnamenode
shouldstorethenametable.Ifthisisacomma-delimitedlistofdirectories
thenthenametableisreplicatedinallofthedirectories,
forredundancy.
dfs.data.dir
/home/caoyuz/hadoopfs/data
DetermineswhereonthelocalfilesystemanDFSdatanode
shouldstoreitsblocks.Ifthisisacomma-delimitedlistofdirectories,
thendatawillbestoredinallnameddirectories,typicallyondifferentdevices.
Directoriesthatdonotexistareignored.
dfs.replication
2
Defaultblockreplication.Theactualnumberofreplications
canbespecifiedwhenthefileiscreated.Thedefaultisusedifreplication
isnotspecifiedincreatetime.
参数fs.default.name指定NameNode的IP地址和端口号,此处我们将其设定为homer06及9000端口,参数mapred.job.tracker指定JobTracker的IP地址和端口号,此处我们将其设定为homer06及9001端口。
参数dfs.name.dir指定NameNode相关数据在本地文件系统上的存放位置,此处我们将其设定为/home/caoyuz/hadoopfs/name,参数dfs.data.dir指定DataNode相关数据在本地文件系统上的存放位置,此处我们将其设定为/home/caoyuz/hadoopfs/data。
注意,Hadoop会自动创建这两个目录,无需事先创建。
更多的参数配置,可以参考conf/hadoop-default.xml文件,并在conf/hadoop-site.xml文件中设置。
4.设定主从节点
修改conf/masters文件,将其中的localhost改为homer06,修改conf/slaves文件,删掉其中的localhost,将我们的另两台机器homer07,homer08加入,注意每个机器一行。
5.将Hadoop部署到其它机器上去
至此,我们已经在homer06上安装和配置好了hadoop和jre,现在需要将其部署到其它机器上去,通过scp命令即可完成,如代码清单3所示:
代码清单3
homer06:
$scp-r/home/caoyuz/hadoop-0.16.0homer07:
/home/caoyuz/hadoop-0.16.0
homer06:
$scp-r/home/caoyuz/jrehomer07:
/home/caoyuz/jre
homer06:
$scp-r/home/caoyuz/hadoop-0.16.0homer08:
/home/caoyuz/hadoop-0.16.0
homer06:
$scp-r/home/caoyuz/jrehomer08:
/home/caoyuz/jre
其中用scp拷贝jre目录到其它机器上去不是必须的。
你只需保证你的所有机器上均安装了JRE1.5以上版本,并且都是安装在同一目录。
6.在homer06上格式化一个新的分布式文件系统
如代码清单4所示:
代码清单4
homer06:
$cd/home/caoyuz/hadoop-0.16.0
homer06:
$bin/hadoopnamenode-format
7.在homer06上启动hadoop进程
如代码清单5所示:
代码清单5
homer06:
$cd/home/caoyuz/hadoop-0.16.0
homer06:
$bin/start-all.sh
启动完成之后,运行ps-ef命令应该可以看到homer06上启动了3个新的java进程(namenode,secondarynamenode,jobtracker),同时,我们可以到homer07,homer08两台机器上用ps–ef查看,这两台机器上应该已经自动启动了2个新的java进程(datanode,tasktracker)
回页首
四运行Hadoop程序
至此,整个Hadoop分布式环境已经部署完毕,并已启动相关后台进程。
现在我们可以尝试运行一下我们在第二篇文章中介绍的wordcount程序,如代码清单6所示:
代码清单6
homer06:
$mkdir-p/home/test-in
#请先将待测的文件放到本地文件系统的/home/test-in目录
homer06:
$cd/home/caoyuz/hadoop-0.16.0
homer06:
$bin/hadoopdfs–put/home/test-ininput
#将本地文件系统上的/home/test-in目录拷到HDFS的根目录上,目录名改为input
$bin/hadoopjarhadoop-0.16.0-examples.jarwordcountinputoutput
#查看执行结果:
#将文件从HDFS拷到本地文件系统中再查看:
$bin/hadoopdfs-getoutputoutput
$catoutput/*
#也可以直接查看
$bin/hadoopdfs-catoutput/*
代码清单6所示的执行wordcount程序的过程,与我们在第一篇文章中介绍的在伪分布式运行环境运行完全一致,但我们现在拥有了一个真正的分布式执行环境,我们的数据分布存储于数据节点homer07及homer08上,可以在这两台机器的/home/caoyuz/hadoopfs/data目录(这是我们在conf/hadoop-site.xml中指定的dfs.data.dir参数)下看到一些数据文件,并且整个wordcount的计算过程神奇地由homer06,homer07,homer08三台机器并行协同完成,我们还可以很方便的增加更多的机器来参与运算。
这就是分布式并行程序的优势:
可以很容易地通过加入新的机器来获得更多的存储空间和计算能力,部署的机器越多,就越能有效地完成海量数据的计算。
回页首
五使用IBMMapReduceTools部署分布式程序
在第二篇文章中,已经介绍了IBMMapReduceTools的基本功能和用法。
现在我们重点介绍如何使用IBMMapReduceTools将MapReduce程序远程部署到Hadoop分布式环境中去运行。
假定我们还是使用上一节部署完成的分布式环境,然后是在另一台机器上使用Eclipse开发MapReduce程序。
1.定义Hadoopserver的位置
首先请确保你的Eclipse已经安装了IBMMapReduceTools这个插件。
启动Eclipse,选择Window->OpenPerspective->other,再从弹出框中选择MapReduce,这样Eclipse会进入专门的MapReduce视图(perspective)。
随后,请检查你的MapReduceperspective中是否有一个专门的MapReduceServersview,如果没有,请选择Window->ShowView->other,再从弹出框中选择MapReduceTools类别下面的MapReduceServers,打开这个view.
然后,请点击 MapReduceServersview右上角的蓝色图标,就会出现如图一所示的设置HadoopServer的位置的界面。
此处所说的Hadoopserver,具体到本文,就是homer06这台机器。
在输入各项参数之后,请点击”Validatelocation”按钮,检查是否能够正确的找到并连接上你的Hadoopserver.如果出错,请尝试在命令行下执行命令:
sshthe_hostname_of_your_hadoop_server,(或使用图形界面的SSH远程登录软件),确保ssh能够连接成功。
图一定义Hadoopserver的位置
2.创立一个MapReduceProject
在Eclipse中新创建一个MapReduceProject,将我们在第二篇文章中定义的WordCount类加到此Project中。
这个类需要略作修改才能直接远程部署到我们已经搭建好的分布式环境中去运行,因为我们原来在 WordCount 程序中是通过读取命令行参数获得计算任务的输入路径和输出路径,而当前版本的IBMMapReduceTools不支持远程部署时读取命令行参数。
为测试的简便起见,我在程序中直接将输入路径定义为input,输出路径定义为output。
在测试WordCount程序之前,需要事先将需要做词频统计的一批文件拷贝到分布式文件系统的input目录下去。
完整的WordCount类的代码如代码清单7所示:
代码清单7
//import语句省略
publicclassWordCountextendsConfiguredimplementsTool{
publicstaticclassMapClassextendsMapReduceBase
implementsMapper{
privatefinalstaticIntWritableone=newIntWritable
(1);
privateTextword=newText();
privateStringpattern="[^\\w]";
publicvoidmap(LongWritablekey,Textvalue,
OutputCollectoroutput,
Reporterreporter)throwsIOException{
Stringline=value.toString().toLowerCase();
line=line.replaceAll(pattern,"");
StringTokenizeritr=newStringTokenizer(line);
while(itr.hasMoreTokens()){
word.set(itr.nextToken());
output.collect(word,one);
}
}
}
publicstaticclassReduceextendsMapReduceBase
implementsReducer{
publicvoidreduce(Textkey,Iteratorvalues,
OutputCollectoroutput,
Reporterreporter)throwsIOException{
intsum=0;
while(values.hasNext()){
sum+=values.next().get();
}
output.collect(key,newIntWritable(sum));
}
}
publicintrun(String[]args)throwsException{
PathtempDir=newPath("wordcount-temp-"+
Integer.toString(newRandom().nextInt(Integer.MAX_VALUE)));
JobConfconf=newJobConf(getConf(),WordCount.class);
try{
conf.setJobName("wordcount");
conf.setOutputKeyClass(Text.class);
conf.setOutputValueClass(IntWritable.clas