您的位置:首页 > 运维架构

hadoop hdfs搭建 mapreduce环境搭建 wordcount程序简单注释

2011-08-22 18:15 906 查看

一 实验室环境下 hadoop集群配置

一、环境说明

实验室中多台机器都属于同一局域网,主机的操作系统多为windows系统,而hadoop要在linux环境下配置,因此我们选用了host(windows7)+Vmware(ubuntu)的方式进行了实验性的配置。
机器三台,分别做namenode(12G内存 八核处理器 1TB硬盘)和两个datanode(4G内存双核处理器 1TB硬盘)。下面进入正式的配置过程。

二、虚拟机的安装及上网方式的选择

虚拟机上网方式,选择桥接。

虚拟机器上安装linux(ubuntu)系统,上网方式:选择有线网络,手动设置IP。网关。IP与主机网段相同。网关与主机相同,DNS与主机相同。

我们这次试验中 机器的配置的ip结果如下

Datanode : 219.245.72.244

Namenode1: 219.245.72.242

Namenode2: 219.245.72.243

这是如果网络是好的,各个linux系统之间可以ping通。

三、安装ssh服务

在安装之前把虚拟机的上网方式改成Nat,Bridge方式不能直接上网。Linux系统设置成自动获取ip。

下面安装openssh-server ,并配置各节点的公钥私钥

对于每个节点:

安装 openssh-server :sudo apt-get install openssh-server

创建公钥私钥: ssh-keygen –t rsa

期间会要求输入一些信息,直接按回车就可以。这样,在默认的路径(其中 njust 是当前用户名) /home/lilin/.ssh 目录下创建 私钥 id_rsa 和一个公钥 id_rsa.pub 。

对于 datanode 节点:

将自己的公钥发送到 namenode 上:

cp id_rsa.pubdatanode1.id_rsa.pub

scpdatanode01.id_rsa.pub namenode 节点 ip 地址(在我的配置方案中,是219.245.72.244):/home/lilin/.ssh

这里需要注意,由于每个 datanode 节点都要将自己的公钥传到 namenode 的相同路径下,因此,各个 datanode 发送的公钥文件名不能相同。这里使用 cp 命令,在每台 datanode 节点上将公钥文件复制为唯一名字的文件。

对于 namenode 节点:

在收到所有 datanode 发送过来的公钥文件之后,要综合这些文件(包括自身),并将这些文件发送到每个节点上:

cp id_rsa.pubauthorized_keys

cat datanode1.id_rsa.pub>> authorized_keys

cat datanode2.id_rsa.pub>> authorized_keys

scpauthorized_keys datanode的ip地址:/home/lilin/.ssh

这时一定要查看一下 ssh 配置是否成功,查看方式是使用 ssh 命令: ssh 其他机器ip ,如果不需要密码就可以登录,就说明配置成功。如果还需要密码,干脆无法登录,则需要重启电脑。重启之后再次使用 ssh 命令,如果还需要密码或者无法登录,则需要重新配置一遍。

成功之后namenode可以无密码登录datanode节点。

注意:这里能否成功是工作能否继续进行的一个关键。一定要能够各个机器之间能够ssh通畅,ssh是linux传递文件的保障,只有能够互相ssh我们各个机器之间传递的信息才是安全的。在这里,在我们的配置过程中出现了许多麻烦,因为以前对linux系统也没有接触过,吃了不少亏。

四、开始集群配置

1、修改各主机的主机名,以区分不同的机器:

打开/etc/hostname:sudo gedit /etc/hostname

对于namenode节点:

将主机名改成namenode,datanode改成相应的datanode1,datanode2等等,并保存关闭。如下图所示:

2、配置各个主机之间IP与主机名的对应关系
修改集群中各个主机的/etc/hosts文件:sudo gedit /etc/hosts

将集群中各个主机的IP与主机名都列在此处,如图所示:

注意要将第一行注释掉:#127.0.0.1localhost.localdomain localhost

注意:如果是第一次接触到linux系统的人,会更改不了。这里要对文件的权限进行修改。命令如下:

Chmod 777 /etc/hosts

这样就可更改hosts的内容了 对于以后要处理的文件不在赘述,都是用这种方法更改文件权限后就可以操作

3. 安装 JDK 1.6

root用户登陆,在Namenode节点上新建文件夹/usr/program,下载JDK安装包jdk-6u13-linux-i586.bin,复制到目录/usr/ program下,在命令行进入该目录,执行命令“./ jdk-6u13-linux-i586.bin”,命令运行完毕,将在目录下生成文件夹jdk1.6.0_13,安装完毕。

安装完成后,修改/usr/program目录拥有着为lilin用户.若果只有一个用户当然就不用修改了。

下面进行环境变量配置

root用户登陆,命令行中执行命令”sudogedit /etc/profile”,并加入以下内容,配置环境变量(注意/etc/profile这个文件很重要,后面Hadoop的配置还会用到)。

# set java environment

export JAVA_HOME=/usr/program/jdk1.6.0_13/

export JRE_HOME=/usr/program/jdk1.6.0_13/jre

export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib

export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH

保存并退出,执行以下命令使配置生效

chmod +x /etc/profile

source /etc/profile

配置完毕,在命令行中使用命令”java -version”可以判断是否成功。在lilin用户下测试java –version,一样成功。

4、Hadoop集群配置

在namenode上执行:

Hadoop用户登录。

下载hadoop-0.21.0,将其解压到/usr/local/hadoop目录下,解压后目录形式是/usr/local/hadoop/hadoop-0.21.0。使用如下命令:

tar zxvf hadoop-0.21.0.tar.gz

(1)配置Hadoop的配置文件

(a)配置hadoop-env.sh

# set java environment

export JAVA_HOME=/usr/program/jdk1.6.0_13/

(b)配置conf/hadoop-site.xml

Hadoop配置参数的含义请参考conf/Hadoop-default.xml。

Hadoop-0.20之后的版本请分别配置hadoop目录下,conf目录中的core-site.xml,hdfs-site.xml和mapred-site.xml三个配置文件,配置方法即将下面hadoop-site.xml文件中的三块参数分别复制到三个文件当中。

<?xml version="1.0"?>

<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<!-- Put site-specific property overrides in this file. -->

<configuration>

<!—core-site.xml-->

<property>

<name>fs.default.name</name>

<value>hdfs://lilin:9000</value>

<description>HDFS的URI,文件系统://namenode标识:端口号</description>

</property>

<property>

<name>hadoop.tmp.dir</name>

<value>/usr/local/hadoop/hadooptmp</value>

<description>namenode上本地的hadoop临时文件夹</description>

</property>

<!—hdfs-site.xml-->

<property>

<name>dfs.name.dir</name>

<value>/usr/local/hadoop/hdfs/name</value>

<description>namenode上存储hdfs名字空间元数据 </description>

</property>

<property>

<name>dfs.data.dir</name>

<value>/usr/local/hadoop/hdfs/data</value>

<description>datanode上数据块的物理存储位置</description>

</property>

<property>

<name>dfs.replication</name>

<value>2</value>

<description>副本个数,不配置默认是3,应小于datanode机器数量</description>

</property>

<!—mapred-site.xml-->

<property>

<name>mapred.job.tracker</name>

<value>lilin:9001</value>

<description>jobtracker标识:端口号,不是URI</description>

</property>

<property>

<name>mapred.local.dir</name>

<value>/usr/local/hadoop/mapred/local</value>

<description>tasktracker上执行mapreduce程序时的本地目录</description>

</property>

<property>

<name>mapred.system.dir</name>

<value>/tmp/hadoop/mapred/system</value>

<description>这个是hdfs中的目录,存储执行mr程序时的共享文件</description>

</property>

</configuration>

(c)配置masters文件,加入namenode的主机名

Lilin

(d)配置slaves文件, 加入所有datanode的主机名

Lilin

Lilin

复制配置好的各文件到所有数据节点上

root用户下:

scp /etc/hosts 数据节点ip地址:/etc/hosts

scp /etc/profile 数据节点ip地址:/etc/profile

scp /usr/program 数据节点ip地址:/usr/program

nutch用户下:

scp /usr/local/hadoop 数据节点ip地址: /usr/local/

5、Hadoop集群启动
Namenode执行:

格式化namenode,格式化后在namenode生成了hdfs/name文件夹

cd/usr/local/hadoop/hadoop-0.21.0/bin

bin$ ./hadoopnamenode –format

启动hadoop所有进程,

bin/start-all.sh(或者先后执行start-dfs.sh和start-mapreduce.sh)。

可以通过以下启动日志看出,首先启动namenode,然后启动datanode1,datanode2,然后启动secondarynamenode。再启动jobtracker,然后启动tasktracker1,最后启动tasktracker2。下面是集群启动的结果

下面检查一下namenode上的进程。用jps工具检查就可以了

上边是namenode的进程运行情况。下边是datanode进程运行情况

下面检查一下集群的运行情况

命令:在bin下 运行命令 hadoop dfsadmin –report

到此为止,我们的hadoop集群配置已经完成,集群正常运行。可以进行其他的实验了。

首先上传文件

hadoop fs –put 源地址目的地址

上传成功后查看文件

然后我们继续观察下面的测试结果

看到在hdfs的used中已经增加了许多。

下边跑一个例子程序

在程序之前我们看一下在hadoop的hdfs系统中的input01文件中的文件内容

下面我们运行hadoop的自带的wordcount程序

运行之后 我们看一下程序的运行结果

至此hadoop 的hdfs环境已经好了,可以跑mapreduce程序了。

二 伪分布式Mapreduce开发环境配置

Eclipse版本eclipse-jee-galileo-SR1-linux-gtk

hadoop版本 0.20.2

开始配置

第一步 配置 hadoop conf下的三个文件

core-site.xml

这个设置的是hdfs的机器名和端口

hdfs-site.xml

这个设置了dfs的数据副本个数

mapre-site.xml

这个设置了mapreduce的jobtracker的工作端口

第一步,我们先启动Hadoop守护进程。

start-all.sh

如果namenode没有启动起来 建议你

hadoop namenode -format

然后再启动 jps下 看是否启动成功 如果启动成功 如下图

第二步,在Eclipse下安装hadoop-plugin。

1.复制 hadoop安装目录/contrib/eclipse-plugin/hadoop-0.20.2-eclipse-plugin.jar 到 eclipse安装目录/plugins/ 下。

2.重启eclipse,配置hadoop installation directory。

如果安装插件成功,打开Window-->Preferens,你会发现Hadoop Map/Reduce选项,在这个选项里你需要配置Hadoop installationdirectory。配置完成后退出。

3.配置Map/Reduce Locations。

在Window-->ShowView中打开Map/ReduceLocations。

在Map/ReduceLocations中新建一个HadoopLocation。在这个View中,右键-->New Hadoop Location。在弹出的对话框中你需要配置Location name,如myubuntu,还有Map/Reduce Master和DFS Master。这里面的Host、Port分别为你在mapred-site.xml、core-site.xml中配置的地址及端口。如:

这里要注意 Username一定要填写正确 不然后边会有麻烦

配置完后退出。点击DFSLocations-->hadoop如果能显示文件夹(2)说明配置正确,如果显示"拒绝连接",请检查你的配置

这就正确了

第三步,新建项目。

File-->New-->Other-->Map/Reduce Project

项目名可以随便取,如hadoop-test。

复制 hadoop安装目录/src/example/org/apache/hadoop/example/WordCount.java到刚才新建的项目下面。

第四步,运行项目。

1.在新建的项目hadoop-test,点击WordCount.java,右键-->Run As-->Run Configurations

2.在弹出的Run Configurations对话框中,点Java Application,右键-->New,这时会新建一个application名为WordCount

3.配置运行参数,点Arguments,在Program arguments中输入“你要传给程序的输入文件夹和你要求程序将计算结果保存的文件夹”,如:

4.点击Run,运行程序。

查看目录 在user目录下 多了我们设置的output03

查看output03中的内容

结果正确。

需要注意的问题:

1,版本问题如果hadoop的eclipse-plugin.jar放到Eclipse下的Plugin下后 在ShowWindow中看不到

MapReduce的时候,很可能是版本不同,这个jar包是hadoop的源代码编译出来的 ,如果实在版本不可以,你可以自己编译自己的这个包,方法如下

一,安装ant 1.8.2

1、把apache-ant-1.8.2-bin.tar.gz解压到/usr/apache-ant-1.8.2

2、设置/etc/profile:

export ANT_HOME=/usr/apache-ant-1.8.2

export PATH=$PATH:$ANT_HOME/bin

二、生成hadoopeclipse plugin

1、修改/usr/local/hadoop/hadoop-0.20.2/build.xml:

修改<property name="version" value="0.20.2"/>

2、修改/usr/local/hadoop/hadoop-0.20.2/src/contrib/build-contrib.xml:

添加<property name="eclipse.home"location="/home/hadoop/eclipse3.4.2"/>

3、修改

/usr/local/hadoop/hadoop-0.20.2/src/contrib/eclipse-plugin/src/java/org/apache/hadoop/eclipse/launch/HadoopApplicationLaunchShortcut.java

注释掉原来的这个import包//importorg.eclipse.jdt.internal.debug.ui.launcher.JavaApplicationLaunchShortcut;

改为

import

org.eclipse.jdt.debug.ui.launchConfigurations.JavaApplicationLaunchShortcut;

4、下载apache-forrest-0.8.tar.gz,解压到/home/hadoop/apache-forrest-0.8。

5、编译并打包

$ cd /usr/local/haoop/hdoop-0.20.2

$ ant compile

$ln -sf /usr/local/hadoop/hadoop-0.20.2/docs/usr/local/hadoop/hadoop-0.20.2/build/docs

$ ant package

如果成功的话,会在/usr/local/hadoop/hadoop-0.20.2/build/contrib/eclipse-plugin

下生成hadoop-0.20.2-eclipse-plugin.jar。

把这个考进去 就没问题了。

还有这个hadoop-0.20.2-eclipse-plugin.jar在不同的版本里位置可能不同,搜下就找到了。

2,在运行程序的时候有时候会出现内存不足的情况 如下设置就可以了

这样就可以了,就是设置一下虚拟机的内存

3,在设置好Eclipse之后 经常出现不能显示HDFS目录的状况

这是要检查的地方有几个

Define Hadoop location 的User name

配置文件端口 是否与端口号一致

4,namenode没有启动 重新format一下就可以了

5,一定要先上传到hdfs文件后才能查到Eclipse下的hdfs目录。否则是看不到目录的

wordCount 程序注释

下边是我注释的wordcount程序

packageorg.apache.hadoop.examples;

importjava.io.IOException;

importjava.util.StringTokenizer;

importorg.apache.hadoop.conf.Configuration;

importorg.apache.hadoop.fs.Path;

importorg.apache.hadoop.io.IntWritable;

importorg.apache.hadoop.io.Text;

importorg.apache.hadoop.mapreduce.Job;

importorg.apache.hadoop.mapreduce.Mapper;

importorg.apache.hadoop.mapreduce.Reducer;

importorg.apache.hadoop.mapreduce.lib.input.FileInputFormat;

importorg.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

importorg.apache.hadoop.util.GenericOptionsParser;

public classWordCount {

/**

MapReduceBase类:实现了Mapper和Reducer接口的基类(其中的方法只是实现接口,而未作任何事情)

Mapper接口:

WritableComparable接口:实现WritableComparable的类可以相互比较。所有被用作key的类应该实现此接口。

Reporter 则可用于报告整个应用的运行进度,本例中未使用。

LongWritable,IntWritable, Text 均是 Hadoop 中实现的用于封装 Java 数据类型的类,这些类实现了WritableComparable接口,都能够被串行化从而便于在分布式环境中进行数据交换,你可以将它们分别视为long,int,String 的替代品。

**/

public static classTokenizerMapper

extendsMapper<Object, Text, Text, IntWritable>{

private final staticIntWritable one = new IntWritable(1);

private Text word =new Text();

/**

Mapper接口中的map方法,

Void map(K1key, V1value, OutputCollector<K2,V2> output, Reporter reporter)

映射一个单个的输入k/v对到一个中间的k/v对

输出对不需要和输入对有相同的类型,输入对可以对应不同数量的输出对

OutputCollector接口:收集Mapper和Reducer输出的<k,v>对

OutputColletctor接口的collect(k,v)方法,增加一个(k/v)对到output

**/

public voidmap(Object key, Text value, Context context

) throwsIOException,InterruptedException {

StringTokenizer itr =new StringTokenizer(value.toString());

while(itr.hasMoreTokens()) {

word.set(itr.nextToken());

context.write(word,one);

}

}

}

public static classIntSumReducer

extendsReducer<Text,IntWritable,Text,IntWritable> {

private IntWritableresult = new IntWritable();

public voidreduce(Text key, Iterable<IntWritable> values,

Context context

) throwsIOException,InterruptedException {

int sum = 0;

for (IntWritable val: values) {

sum += val.get();

}

result.set(sum);

context.write(key,result);

}

}

publicstatic voidmain(String[] args) throws Exception

{

/**

* JobConf:map/reduce的job配置类,向hadoop框架描述map-reduce执行的工作

* 构造方法:JobConf()、JobConf(ClassexampleClass)、JobConf(Configuration conf)等

*/

JobConf conf = newJobConf(WordCount.class);

conf.setJobName("wordcount");//设置一个用户定义的job名称

conf.setOutputKeyClass(Text.class);//为job的输出数据设置Key类

conf.setOutputValueClass(IntWritable.class);//为job输出设置value类

conf.setMapperClass(Map.class);//为job设置Mapper类

conf.setCombinerClass(Reduce.class);//为job设置Combiner类

conf.setReducerClass(Reduce.class);//为job设置Reduce类

conf.setInputFormat(TextInputFormat.class);//为map-reduce任务设置InputFormat实现类

conf.setOutputFormat(TextOutputFormat.class);//为map-reduce任务设置OutputFormat实现类

/**

* InputFormat描述map-reduce中对job的输入定义

* setInputPaths():为map-reducejob设置路径数组作为输入列表

* setInputPath():为map-reducejob设置路径数组作为输出列表

*/

FileInputFormat.setInputPaths(conf,newPath(args[0]));

FileOutputFormat.setOutputPath(conf,newPath(args[1]));

JobClient.runJob(conf);//运行一个job

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: