1 配置文件

首先看一下hadoop的配置文件, 2.7.0版本中, 配置文件位于etc/hadoop/目录下,其中后缀带有”-site”的文件如core-site.xml, hdfs-site.xml, mapred-site.xml, yarn-site.xml是site相关的, 也就是说需要为集群中的每个site单独配置,当然其中有些是共通的. 还有个hadoop-env.sh用于配置环境变量. 此外还有个slave文件, 用于告诉master有哪几个slave. 配置hadoop集群主要就用到这几个配置文件.

hadoop-env.sh

这个文件用于为hadoop提供JAVA_HOME环境变量, 需要手动把其中的

export JAVA_HOME={$JAVA_HOME}

改成系统JAVA_HOME目录, 如

export JAVA_HOME=/usr/lib/jvm/java

注意最后没有斜杠.

core-site.xml

在configuration标签中添加以下信息:

<property>
  <name>fs.defaultFS</name>
  <value>hdfs://ubuntu-189:9000</value>
</property>

其中ubuntu-189为master主机的ip或者域名.

hdfs-site.xml

<property>
  <name>dfs.namenode.name.dir</name>
  <value>/home/hadoop/hdfsdata</value>
</property>
<property>
  <name>dfs.replication</name>
  <value>1</value>
</property>

此处将replication设置为1, 即没有备份. 另外通过dfs.namenode.name.dir设置namenode的数据存放位置.

这里还能设置其他参数:

Parameter Value
dfs.hosts allowable datanodes
dfs.hosts.exlcude disallowable datanodes
dfs.blocksize block size(in B)
dfs.namenode.handler.count namenode server threads to handle RPCs from datanodes

mapred-site.xml

<property>
  <name>mapreduce.framework.name</name>
  <value>yarn</value>
</property>

此处通过设置mapreduce.framework.name的值为yarn, 来指定yarn作为调度器, 否则的话在运行mapreduce任务时只会在本地进行调度.

yarn-site.xml

<property>
  <name>yarn.resourcemanager.hostname</name>
  <value>ubuntu-189</value>
</property>
<property>
  <name>yarn.nodemanager.aux-services</name>
  <value>mapreduce_shuffle</value>
</property>

slaves

输入slave主机的ip地址, 每行一个, 如

arc184
ubuntu-183

此文件用户start-dfs.sh和start-yarn.sh脚本快速启动各个slave, 省的一个个登录到slave主机上启动hdfs和yarn了.

其他配置

ssh

集群中的机器通信需要ssh免密登录, 因此slave和master需要有相同的用户名, 并互相配置成免密登录.

.bashrc

在.bashrc中需要配置JAVA_HOME, HADOOP_HOME等信息, 具体配置如下:

export JAVA_HOME=/usr/lib/jvm/java
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
export HADOOP_INSTALL=/home/hadoop/hadoop/
export HADOOP_MAPRED_HOME=$HADOOP_INSTALL
export HADOOP_COMMON_HOME=$HADOOP_INSTALL
export HADOOP_HDFS_HOME=$HADOOP_INSTALL
export YARN_HOME=$HADOOP_INSTALL
export HADOOP_PREFIX=/home/hadoop/hadoop
export HADOOP_CLASSPATH=${JAVA_HOME}/lib/tools.jar

hosts

官网资料上面配置时用的是master, slave1, slave2, 需要在hosts中配置这些主机名对应的ip地址. 同时, 如果系统本身的主机名如果不是master, slave1, slave2等, 要么改成一致, 要么在hosts中添加系统主机名与相应ip地址的映射. 例如, 我作为master主机的主机名是ubuntu-189, 而在hosts中这个ubuntu-189 对应的ip地址设置成了127.0.0.1, master设置成了10.214.144.189. 如果直接这么运行, 会出现服务始终启动在localhost上(因为127.0.0.1除了对应ubunut-189以外还对应了localhost, 在做反向域名解析的时候被解析到了localhost)的错误, 导致其他节点想访问ubuntu-189的时候(hadoop直接使用主机名而不是使用自己定义的master), 访问到了127.0.0.1上去了. 解决方法如前面所说, 要么使用sudo hostname master将ubuntu-189改成master, 要么将ubuntu-189映射到实际的ip地址10.214.144.189而非127.0.0.1. 书上和官网文档都用master, slave做例子, 却不说明这个master和slave需要和主机的主机名一致才行, 多走了不少弯路.

2 启动

启动hdfs

首先需要对hdfs格式化, 如果之前已经格式化过, 而后来又改了配置, 直接跳过这步可能会导致莫名其妙的错误, 最好先格式化一下:

bin/hdfs namenode -format

然后可以启动:

sbin/start-dfs.sh

检测是否启动成功:

bin/hdfs dfs -mkdir /user
bin/hdfs dfs -mkdir /user/hadoop
bin/hdfs dfs -put etc/hadoop input

或者在浏览器中输入master:50070查看. 如果发现Live Nodes为0, 可能是slave 在向master发送心跳包的时候被防火墙拒绝了. 可以通过查看slave端的日志来获取详细错误信息.

启动yarn

sbin/start-yarn.sh

如果启动时查看日志出现以下错误:

2015-07-09 19:59:01,078 INFO org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeImpl: slave1:50990 Node Transitioned from NEW to RUNNING
2015-07-09 19:59:01,079 INFO org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler: Added node slave1:50990 clusterResource: <memory:16384, vCores:16>
2015-07-09 19:59:01,113 INFO org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeImpl: Node slave1:50990 reported UNHEALTHY with details: 1/1 local-dirs are bad: /home/hadoop/yarn_dirs; 1/1 log-\
dirs are bad: /home/hadoop/yarn_dirs
2015-07-09 19:59:01,115 INFO org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeImpl: slave1:50990 Node Transitioned from RUNNING to UNHEALTHY
2015-07-09 19:59:01,116 INFO org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler: Removed node slave1:50990 clusterResource: <memory:8192, vCores:8>

有几种原因, 一是磁盘可用空间小于10%. 这需要清理空间, 或者放到另一个设备上去. 但是试了一下还是不行, 不知道为什么. 只有清理空间了. 还有一种原因是用户权限不对. 这个文件夹不用手动创建, yarn在启动时如果发现不存在会自己创建.

启动mapred测试程序

$ bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.0.jar grep input output 'dfs[a-z.]+'

查看程序输出:

$ bin/hdfs dfs -cat output/*

3 运行WordCount

首先要确保正确安装了jdk, 在Ubuntu下之前安装了openjdk-7-headless, 结果没有javac. 重新sudo apt-get install openjdk-7-jdk解决. 然后从官网复制以下代码:

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;

public class WordCount {

  public static class TokenizerMapper
       extends Mapper<Object, Text, Text, IntWritable>{

    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();

    public 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();

    public 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 conf = new Configuration();
    Job job = Job.getInstance(conf, "word count");
    job.setJarByClass(WordCount.class);
    job.setMapperClass(TokenizerMapper.class);
    job.setCombinerClass(IntSumReducer.class);
    job.setReducerClass(IntSumReducer.class);
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);
    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    System.exit(job.waitForCompletion(true) ? 0 : 1);
  }
}

编译并打包成jar:

$ bin/hadoop com.sun.tools.javac.Main WordCount.java
$ jar cf wc.jar WordCount*.class

新建两个文件, 随便输入点内容. 然后:

$ bin/hdfs dfs -mkdir /user/hadoop/wordcount/
$ bin/hdfs dfs -mkdir /user/hadoop/wordcount/input
$ bin/hdfs dfs -put ../wordcount/file* /user/hadoop/wordcount/input

如果在最后一步put的时候发现很多java exception, 可能是datanode没启动起来, 查看日志找原因. 如果之前重新format过, 很有可能是datanode的数据没有被格式化导致cluster id不一致. 删除data.dir目录下的东西就行.

运行:

$ bin/hadoop jar ../wordcount/wc.jar WordCount /user/hadoop/wordcount/input /user/hadoop/wordcount/output

查看输出结果, 位于hdfs的output文件夹:

$ bin/hdfs dfs -ls /user/hadoop/wordcount/output
Found 2 items
-rw-r--r--   1 hadoop supergroup          0 2015-07-08 16:12 /user/hadoop/wordcount/output/_SUCCESS
-rw-r--r--   1 hadoop supergroup         47 2015-07-08 16:12 /user/hadoop/wordcount/output/part-r-00000

查看内容:

$ bin/hdfs dfs -cat /user/hadoop/wordcount/output/part-r-00000
By      1
Goodbye 1
Hadoop  2
Hello   1
Helo    1
World   2

至此, 多节点集群环境搭建完毕, 可以开始码代码了.

4 其他资料

Hadoop组件默认端口

组件 结点 默认端口 配置 用途
HDFS DataNode 50075 dfs.datanode.http.address http服务的端口
HDFS DataNode 50475 dfs.datanode.https.address https服务的端口
HDFS DataNode 50020 dfs.datanode.ipc.address ipc服务的端口
HDFS NameNode 50070 dfs.namenode.http-address http服务的端口
HDFS NameNode 50470 dfs.namenode.https-address https服务的端口
HDFS NameNode 8020 fs.defaultFS 接收Client连接的RPC端口,用于获取文件系统metadata信息。
HDFS journalnode 8485 dfs.journalnode.rpc-address RPC服务
HDFS journalnode 8480 dfs.journalnode.http-address HTTP服务
HDFS ZKFC 8019 dfs.ha.zkfc.port ZooKeeper FailoverController,用于NN HA
YARN ResourceManager 8032 yarn.resourcemanager.address RM的applications manager(ASM)端口
YARN ResourceManager 8030 yarn.resourcemanager.scheduler.address scheduler组件的IPC端口
YARN ResourceManager 8031 yarn.resourcemanager.resource-tracker.address IPC
YARN ResourceManager 8033 yarn.resourcemanager.admin.address IPC
YARN ResourceManager 8088 yarn.resourcemanager.webapp.address http服务端口
YARN NodeManager 8040 yarn.nodemanager.localizer.address localizer IPC
YARN NodeManager 8042 yarn.nodemanager.webapp.address http服务端口
YARN NodeManager 8041 yarn.nodemanager.address NM中container manager的端口
YARN JobHistory Server 10020 mapreduce.jobhistory.address IPC
YARN JobHistory Server 19888 mapreduce.jobhistory.webapp.address http服务端口
HBase Master 60000 hbase.master.port IPC
HBase Master 60010 hbase.master.info.port http服务端口
HBase RegionServer 60020 hbase.regionserver.port IPC
HBase RegionServer 60030 hbase.regionserver.info.port http服务端口
HBase HQuorumPeer 2181 hbase.zookeeper.property.clientPort HBase-managed ZK mode,使用独立的ZooKeeper集群则不会启用该端口。
HBase HQuorumPeer 2888 hbase.zookeeper.peerport HBase-managed ZK mode,使用独立的ZooKeeper集群则不会启用该端口。
HBase HQuorumPeer 3888 hbase.zookeeper.leaderport HBase-managed ZK mode,使用独立的ZooKeeper集群则不会启用该端口。
Hive Metastore 9083 /etc/default/hive-metastore中export PORT=<port>来更新默认端口  
Hive HiveServer 10000 /etc/hive/conf/hive-env.sh中export HIVE_SERVER2_THRIFT_PORT=<port>  
ZooKeeper Server 2181 /etc/zookeeper/conf/zoo.cfg中clientPort=<port> 对客户端提供服务的端口
ZooKeeper Server 2888 /etc/zookeeper/conf/zoo.cfg中server.x=[hostname]:nnnnn[:nnnnn],标蓝部分 follower用来连接到leader,只在leader上监听该端口。
ZooKeeper Server 3888 /etc/zookeeper/conf/zoo.cfg中server.x=[hostname]:nnnnn[:nnnnn],标蓝部分 用于leader选举的。只在electionAlg是1,2或3(默认)时需要。

Leave a Reply

电子邮件地址不会被公开。 必填项已用*标注

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>