客户机配置
完全分布式模式至少需要三台客户机,我们在笔记1中已经配置了hadoop101,可以参考笔记中的环境配置方法同样配置hadoop102和hadoop103。
分发脚本
我们虽然只有三台客户机,但是配置这么多步骤也很麻烦。我们可以编写脚本xsync,将hadoop101中的文件分发到其他客户机上。
//创建文件夹bin
[hadoop@hadoop101 ~]$ sudo mkdir bin
//进入bin中
[hadoop@hadoop101 ~]$ cd bin/
//创建文件xsync并写入脚本内容
[hadoop@hadoop101 bin]$ sudo vim xsync
#!/bin/bash
#1. 判断参数个数
if [ $# -lt 1 ]
then
echo Not Enough Arguement!
exit;
#!/bin/bash
#1. 判断参数个数
if [ $# -lt 1 ]
then
echo Not Enough Arguement!
exit;
fi
#2. 遍历集群所有机器
for host in hadoop101 hadoop102 hadoop103
do
echo ==================== $host ====================
#3. 遍历所有目录, 挨个发送
for file in $@
do
#4. 判断文件是否存在
if [ -e $file ]
then
#5. 获取父目录
pdir=$(cd -P $(dirname $file); pwd)
#6. 获取当前文件的名称
fname=$(basename $file)
ssh $host "mkdir -p $pdir"
rsync -av $pdir/$fname $host:$pdir
else
echo $file does not exists!
fi
done
done
//设置脚本的权限
[hadoop@hadoop101 bin]$ sudo chmod 777 xsync
//使用分发脚本xsync
[hadoop@hadoop101 ~]$ xsync bin/
我们再到hadoop102、hadoop103中查看bin文件夹,就能看到分发脚本成功。
免密登录SSH
在hadoop101中,如果我们想要登录hadoop102、hadoop103,就需要输入密码,这样太麻烦了。我们现在可以实现免密登录的功能。
//进入.ssh中
[hadoop@hadoop101 ~]$ cd .ssh/
//生成密钥对
[hadoop@hadoop101 .ssh]$ ssh-keygen -t rsa
//复制ssh-copy-id
[hadoop@hadoop101 .ssh]$ ssh-copy-id hadoop101
[hadoop@hadoop101 .ssh]$ ssh-copy-id hadoop102
[hadoop@hadoop101 .ssh]$ ssh-copy-id hadoop103
把上述操作在hadoop102、hadoop103中也执行一遍,这样,我们在任意一台客户机中都可以免密登录其他客户机。
可以看到,我们在hadoop101中登录hadoop102,不再需要密码。
集群的配置与启动
hdfs架构概述
HDFS(Hadoop Distributed File System),是一个分布式文件系统
- NameNode(nn):存储文件的元数据,如文件名,文件目录结构,文件属性(生成时间、副本数、文件权限),以及每个文件的块列表和块所在的DataNode等。
- DataNode(dn):在本地文件系统存储文件块数据,以及块数据的校验和。
- Secondary NameNode(2nn):用来监控HDFS状态的辅助后台程序,每隔一段时间获取HDFS元数据的快照。
yarn架构概述
- ResourceManager(RM)
- 处理客户端请求
- 监控NodeManager
- 启动或监控ApplicationMaster
- 资源的分配与调度
- NodeManager(NM)
- 管理单个节点上的资源
- 处理来自ResourceManager的命令
- 处理来自ApplicationMaster的命令
- ApplicationMaster(AM)
- 负责数据的切分
- 为应用程序申请资源并分配给内部的任务
-
任务的监控与容错
-
Container
-
Container是YARN中的资源抽象,它封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等。
-
集群的配置
hadoop101 | hadoop102 | hadoop103 | |
hdfs | namenode datanode | datanode | Secondarynamenode datanode |
yarn | nodemanager | Resourcemanager nodemanager | nodemanager |
在core-site.xml配置namenode和datanode。
[hadoop@hadoop101 hadoop-3.1.3]$ vim etc/hadoop/core-site.xml
<Configuration>
<!-- 指定 NameNode 的地址 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hadoop101:8020</value>
</property>
<!-- 指定 hadoop 数据的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/module/hadoop-3.1.3/data</value>
</property>
</Configuration>
在hdfs-site.xml配置namenode和secondarynamenode。
[hadoop@hadoop101 hadoop-3.1.3]$ vim etc/hadoop/hdfs-site.xml
<Configuration>
<!-- nn web 端访问地址-->
<property>
<name>dfs.namenode.http-address</name>
<value>hadoop101:9870</value>
</property>
<!-- 2nn web 端访问地址-->
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>hadoop103:9868</value>
</property>
</Configuration>
在yarn-site.xml配置resourcemanager和nodemanger并配置日志聚集。
[hadoop@hadoop101 hadoop-3.1.3]$ vim etc/hadoop/yarn-site.xml
<Configuration>
<!-- 指定 MR 走 shuffle -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!-- 指定 ResourceManager 的地址-->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>hadoop102</value>
</property>
<!-- 环境变量的继承 -->
<property>
<name>yarn.nodemanager.env-whitelist</name>
<value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CO NF_DIR,CLASSPATH_P
REPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAP RED_HOME</value>
</property>
<!-- 开启日志聚集功能 -->
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<!-- 设置日志聚集服务器地址 -->
<property>
<name>yarn.log.server.url</name>
<value>http://hadoop101:19888/jobhistory/logs</value>
</property>
<!-- 设置日志保留时间为 7 天 -->
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>604800</value>
</property>
</Configuration>
在mapred-site.xml配置程序在yarn上执行并配置历史服务器。
[hadoop@hadoop101 hadoop-3.1.3]$ vim etc/hadoop/mapred-site.xml
<Configuration>
<!-- 指定 MapReduce 程序运行在 Yarn 上 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>yarn.app.mapreduce.am.env</name>
<value>HADOOP_MAPRED_HOME=/opt/module/hadoop-3.1.3/etc/hadoop:/opt/module/hadoop-3.1.3/share/hadoop/common/lib/*:/opt/module/hadoop-3.1.3/share/hadoop/common/*:/opt/module/hadoop-3.1.3/share/hadoop/hdfs:/opt/module/hadoop-3.1.3/share/hadoop/hdfs/lib/*:/opt/module/hadoop-3.1.3/share/hadoop/hdfs/*:/opt/module/hadoop-3.1.3/share/hadoop/mapreduce/lib/*:/opt/module/hadoop-3.1.3/share/hadoop/mapreduce/*:/opt/module/hadoop-3.1.3/share/hadoop/yarn:/opt/module/hadoop-3.1.3/share/hadoop/yarn/lib/*:/opt/module/hadoop-3.1.3/share/hadoop/yarn/*</value>
</property>
<property>
<name>mapreduce.map.env</name>
<value>HADOOP_MAPRED_HOME=/opt/module/hadoop-3.1.3/etc/hadoop:/opt/module/hadoop-3.1.3/share/hadoop/common/lib/*:/opt/module/hadoop-3.1.3/share/hadoop/common/*:/opt/module/hadoop-3.1.3/share/hadoop/hdfs:/opt/module/hadoop-3.1.3/share/hadoop/hdfs/lib/*:/opt/module/hadoop-3.1.3/share/hadoop/hdfs/*:/opt/module/hadoop-3.1.3/share/hadoop/mapreduce/lib/*:/opt/module/hadoop-3.1.3/share/hadoop/mapreduce/*:/opt/module/hadoop-3.1.3/share/hadoop/yarn:/opt/module/hadoop-3.1.3/share/hadoop/yarn/lib/*:/opt/module/hadoop-3.1.3/share/hadoop/yarn/*</value>
</property>
<property>
<name>mapreduce.reduce.env</name>
<value>HADOOP_MAPRED_HOME=/opt/module/hadoop-3.1.3/etc/hadoop:/opt/module/hadoop-3.1.3/share/hadoop/common/lib/*:/opt/module/hadoop-3.1.3/share/hadoop/common/*:/opt/module/hadoop-3.1.3/share/hadoop/hdfs:/opt/module/hadoop-3.1.3/share/hadoop/hdfs/lib/*:/opt/module/hadoop-3.1.3/share/hadoop/hdfs/*:/opt/module/hadoop-3.1.3/share/hadoop/mapreduce/lib/*:/opt/module/hadoop-3.1.3/share/hadoop/mapreduce/*:/opt/module/hadoop-3.1.3/share/hadoop/yarn:/opt/module/hadoop-3.1.3/share/hadoop/yarn/lib/*:/opt/module/hadoop-3.1.3/share/hadoop/yarn/*</value>
</property>
<!-- 历史服务器端地址 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>hadoop101:10020</value>
</property>
<!-- 历史服务器 web 端地址 -->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop101:19888</value>
</property>
</Configuration>
workers文件配置,内容是三台客户机的主机名。
[hadoop@hadoop101 hadoop-3.1.3]$ vim etc/hadoop/workers
hadoop101
hadoop102
hadoop103
配置完成后,我们利用刚刚写的脚本分发。
[hadoop@hadoop101 hadoop-3.1.3]$ xsync etc/hadoop/
群起集群
第一次启动集群之前,必须要格式化。
[hadoop@hadoop101 hadoop-3.1.3]$ hdfs namenode -format
然后我们就可以启动集群了 。要注意在哪台客户机里操作。
//启动hdfs
[hadoop@hadoop101 hadoop-3.1.3]$ sbin/start-dfs.sh
//启动yarn
[hadoop@hadoop102 hadoop-3.1.3]$ sbin/start-yarn.sh
//启动历史服务器
[hadoop@hadoop101 hadoop-3.1.3]$ bin/mapred --daemon start historyserver
启动后,我们在每台客户机上都可以用jps命令查看当前进程。如下图所示,说明启动成功。
如果发现进程中有一些奇怪的进程,如RunJar,可以使用如下命令将其关闭。
kill -9 端口号
停止集群时,必须按照启动集群的相反顺序。
//停止历史服务器
[hadoop@hadoop101 hadoop-3.1.3]$ bin/mapred --daemon stop historyserver
//停止yarn
[hadoop@hadoop102 hadoop-3.1.3]$ sbin/stop-yarn.sh
//停止hdfs
[hadoop@hadoop101 hadoop-3.1.3]$ sbin/stop-dfs.sh
常用脚本
我们目前只有三台客户机,如果客户机数量增加,上述的群起集群操作会变得很麻烦。因此,我们可以编写一些常用的脚本,来帮助我们启动集群以及查看进程、检查集群是否启动成功。
我们先编写脚本myhadoop.sh,用来启动和停止集群。
//切到bin中
[hadoop@hadoop101 ~]$ cd bin/
//创建myhadoop.sh脚本文件
[hadoop@hadoop101 bin]$ sudo vim myhadoop.sh
#!/bin/bash
if [ $# -lt 1 ]
then
echo "没有参数输入..."
exit ;
fi
case $1 in
"start")
echo " =================== start hadoop salves ==================="
echo " --------------- start hdfs ---------------"
ssh hadoop101 "/opt/module/hadoop-3.1.3/sbin/start-dfs.sh"
echo " --------------- start yarn ---------------"
ssh hadoop102 "/opt/module/hadoop-3.1.3/sbin/start-yarn.sh"
echo " --------------- start historyserver ---------------"
ssh hadoop101 "/opt/module/hadoop-3.1.3/bin/mapred --daemon start historyser
ver"
;;
"stop")
echo " =================== stop hadoop slaves ==================="
echo " --------------- stop historyserver ---------------"
ssh hadoop101 "/opt/module/hadoop-3.1.3/bin/mapred --daemon stop historyserv
er"
echo " --------------- stop yarn ---------------"
ssh hadoop102 "/opt/module/hadoop-3.1.3/sbin/stop-yarn.sh"
echo " --------------- stop hdfs ---------------"
ssh hadoop101 "/opt/module/hadoop-3.1.3/sbin/stop-dfs.sh"
;;
*)
echo "输入参数错误..."
;;
esac
//赋予权限
[hadoop@hadoop101 bin]$ sudo chmod 777 myhadoop.sh
//启动
[hadoop@hadoop101 bin]$ myhadoop.sh start
//停止
[hadoop@hadoop101 bin]$ myhadoop.sh stop
我们再编写脚本xcall.sh,便于查看客户机的进程。
//创建xcall.sh脚本文件
[hadoop@hadoop101 bin]$ sudo vim xcall.sh
#!/bin/bash
for host in hadoop101 hadoop102 hadoop103
do
echo =============== $host ===============
ssh $host jps
done
//赋予权限
[hadoop@hadoop101 bin]$ sudo chmod 777 xcall.sh
//使用
[hadoop@hadoop101 ~]$ xcall.sh
可以看到,我们的两个脚本编写成功。
简单案例
我们同样做一个简单的wordcount案例,这一次,我们需要统计文本中西游记人物出现的次数。
与单例模式不同,我们可以访问http://hadoop101:9870,在Utilities-Browse the file system中看到我们上传与分析后的数据。
//创建文件xiyou.txt
[hadoop@hadoop101 hadoop-3.1.3]$ vim xiyou.txt
//在hdfs中创建文件目录
[hadoop@hadoop101 hadoop-3.1.3]$ hdfs dfs -mkdir -p /xiyou/input
//上传文件到hdfs中/xiyou/input
[hadoop@hadoop101 hadoop-3.1.3]$ hdfs dfs -put xiyou.csv /xiyou/input
//统计分析
[hadoop@hadoop101 hadoop-3.1.3]$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /xiyou/input/xiyou.txt /xiyou/output
我们在浏览器上查看相应位置,可以看到统计结果。
如果在执行的过程中提示因资源不足而导致mapreduce进程被kill掉,可以先释放资源,把不需要的程序都关掉。如果无法解决问题,可以参考下面这篇博客。