hadoop运行环境搭建-01https://blog.csdn.net/kxj19980524/article/details/88934339
首先准备三台机器,按照上面的做法搭建三台.
配置NTP时间服务器https://blog.csdn.net/kxj19980524/article/details/89433153
scp远程操作
我103机器的software下创建了个文件夹,里面创建了两个文件,把这两个文件使用命令拷贝到104机器上.
这个命令可以在同一局域网的任何一台机器上执行都可以成功. -r表示递归传输,kxj表示用户名,@后面的是ip地址,因为配置了hosts文件所以可以拿那个代替,再后面就是要传输的地址,第一段是文件源地址,第二段是要复制到哪儿去.
scp -r kxj@hadoop103:/opt/software/ch kxj@hadoop104:/opt/software/
下面这种方式也可以 scp 要传输的路径 hadoop102/opt/
ssh远程无密配置
ssh可以通过密码直接登录到别的主机上去,但是在集群的配置中,如果一直使用密码的话,很不方便,并且编写一些脚本的时候也不方便,所以就得配置无密登录
无密登录原理:A想要通过ssh远程连接B的话,需要在A上生成密钥一个公钥一个私钥,然后把公钥复制到B上面一份,再把它添加到授权列表中去.这时,当A向B发送ssh请求时B先会查看是否有A的公钥,如果有的话会使用A的公钥加密生成一个随机字符串,发送给A,A会使用私钥来解密字符串再发送给B,B进行比对,如果正确的话就授权成功了.
这个无密登录是针对用户的,比如kxj这个用户设置了无密登录,root没有设置,那么使用root用户的话,就还得需要密码,设置了root没有设置kxj的话,使用kxj用户也得需要密码,因为它这个密钥都是在当前用户root目录下生成的,每个用户的root目录都不同.
还有这个无密登录是单向的,A机器访问B机器设置了无密登录,B访问A如果不设置的话也得需要密码,所以得互相配置才行.
无密登录配置,ssh-keygen -t rsa 然后按三下回车.
就在这个目录下生成了公钥和私钥
这个文件是记录当前主机访问过哪些主机通过ssh
ssh-copy-id hadoop103,把私钥传给相对应的机器,然后使用ssh就不需要密码了.
其实ssh也得对本机进行一下配置,不然有些命令也是不可以使用的.
进入到hadoop103里面authorized_keys这个文件里存放的就是102的公钥.然后自己把103,104无密登录配置一下.
rsync远程同步工具,主要用于备份和镜像。具有速度快、避免复制相同内容和支持符号链接的优点。
现在103下面有两个文件夹,104下面有三个,使用命令把103下面的同步到104
rsync -rvl /opt/software/ch/ kxj@hadoop104:/opt/software/ch/
执行完命令可以看到,104下面还是三个文件,它这个命令就是不同的文件不删除,相同的文件替换掉.跟scp用法差不多,但是后面两段不能同时都是远程的.我这个命令是在103上执行的,也就是这命令不能在不相关的机器上执行.
xsync同步脚本编写,为的在集群环境过程中同步一些东西.
使用root用户在/usr/local/bin目录下创建xsync文件,因为放这个目录下在任何地方都可以直接执行这个脚本.
touch xsync chmod 777 xsycn
把下面这段放脚本里,如果用户名和我的不同的话进行适当的修改
#!/bin/bash
#1 获取输入参数个数,如果没有参数,直接退出
pcount=$#
if((pcount==0)); then
echo no args;
exit;
fi
#2 获取文件名称
p1=$1
fname=`basename $p1`
echo fname=$fname
#3 获取上级目录到绝对路径
pdir=`cd -P $(dirname $p1); pwd`
echo pdir=$pdir
#4 获取当前用户名称
user=`whoami`
#5 循环
for((host=103; host<105; host++)); do
#echo $pdir/$fname $user@hadoop$host:$pdir
echo --------------- hadoop$host ----------------
rsync -rvl $pdir/$fname $user@hadoop$host:$pdir
done
执行这个命令就在另外两台相同目录下同步过去了,但是执行命令的时候需要密码,所以把root用户也进行ssh无密配置
执行相同命令操作
右键勾上All Session就可以给现在连接的所有session执行相同的命令了,在下面的窗口输入命令,现在连接的session就都执行了.
写个xcall脚本实现简单执行相同命令操作的功能
chmod 777 xcall
#!/bin/bash
pcount=$#
if((pcount==0));then
echo no args;
exit;
fi
echo -------------localhost----------
for((host=102; host<=104; host++)); do
echo ----------hadoop$host---------
ssh hadoop$host $@
done
完全分布式搭建
集群部署规划
hdfs的话,NameNode放在102上,SecondaryNameNode因为是辅助NameNode工作的,两个都耗内存特别大,再一个如果NameNode坏了,也可以从SecondayNameNode复制一份数据成为NameNode.NameNode它会把数据都在SecondayNameNode备份一份,所以把他俩放到不同的机器上.
DataNode每台机器上都得有,其实102有了NameNode不应该放DataNode,为了省一台机器就放上吧.
YARN的话,ResourceManager放103上,因为它也是很耗内存的,得跟NameNode,SecondayNameNode,分开放到不通的机器上.
NodeManager每台也都得有,因为有DataNode就得有NodeManager
开始搭建以下操作都是在102节点上设置
指定NameNode在102节点上
<configuration>
<!-- 指定HDFS中NameNode的地址 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hadoop102:8020</value>
</property>
<!-- 指定hadoop运行时产生文件的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/module/hadoop-2.7.2/data/tmp</value>
</property>
</configuration>
配置hdfs
指定secondaryNameNode配置到104节点
<configuration>
<!-- 默认就是3不设置也行 -->
<!-- <property>
<name>dfs.replication</name>
<value>3</value>
</property> -->
<!-- secondaryNameNode配置到哪台机器 -->
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>hadoop104:50090</value>
</property>
</configuration>
配置datanode节点,空格回车什么都不能有,要求特别严格不然集群就会跑不起来.
配置YARN
指定YARN的ResourceManager的地址为103
配置mapreduce
先把mapred-site.xml.template改为mapred-site.xml
指定mapreduce运行在yarn上
<configuration>
<!-- 指定mr运行在yarn上 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
以上操作只是在102节点配置好了,现在得在103,104都这么配置
在集群上分发以上所有文件,在102节点上使用之前写好的脚本,把hadoop配置文件分发到103,104
xsync hadoop/ 在下面这个目录下执行命令
同步完后执行下面命令查看是否同步成功
[root@hadoop102 etc]# xcall cat /opt/module/hadoop-2.7.2/etc/hadoop/slaves
启动集群
在102节点上初始化namenode记得切换到kxj用户上.上面使用root是为了修改配置文件方便
bin/hdfs namenode -format
启动hdfs
在102上启动集群,可以看到它直接把namenode,secondarynamenode,datanode都启动了
[kxj@hadoop102 hadoop-2.7.2]$ sbin/start-dfs.sh
启动YARN,因为YARN是在103节点上配置的所以必须在103启动,否则启动不成功的.如果启动出错的话先把三个节点上的所有节点关闭,namenode之类的都关闭,然后把hadoop目录下的data目录和logs目录删除掉重新启动.
这样就集群搭建启动成功了!!!!
启动集群后,在hdfs上创建文件夹,然后上传一个小文件上传一个大文件
hadoop fs -mkdir /user/kxj/input
hadoop fs -put /opt/software/hadoop-2.7.2.tar.gz /user/kxj/input
可以看到hadoop文件大小超过了128兆块大小,而kxj.txt没有超过.
小于块128大小的文件在每个节点上备份了一份只有一块,而hadoop文件被分为了两块,每块在每个节点都有备份,也就是说当文件大小大于块内存大小时就会把文件进行拆分存储.
可以尝试找一下集群把文件存放到哪儿了
/opt/module/hadoop-2.7.2/data/tmp/dfs/
之前搭建集群的时候,把存放数据路径设置为了hadoop下面的data目录
进入到这个目录后,会发现102节点有data,name,103,104有data,因为102上部署的namenode所以它有两个文件.
/opt/module/hadoop-2.7.2/data/tmp/dfs/data/current/BP-401392098-192.168.1.102-1554392438574/current/finalized/subdir0/subdir0
最终在这个目录下可以看到有几个blk文件,它其实就是上传上去的文件,可以看到和id相同.
也可以查看它的内容
但是hadoop的压缩包,让拆成两块了怎么使用它呢?其实可以按文件进行拼接一下
touch tmp cat blk_1073741826 >>tmp cat blk_1073741827 >>tmp tar -zxvf tmp
把26和27按顺序拼接到一个文件中,然后直接解压它就可以得到hadoop压缩包
下载测试 hadoop fs -get /user/kxj/input/kxj.txt ./
HDFS中的文件在物理上是分块存储(block),块的大小可以通过配置参数( dfs.blocksize)来规定,默认大小在hadoop2.x版本中是128M,老版本中是64M
HDFS的块比磁盘的块大,其目的是为了最小化寻址开销。如果块设置得足够大,从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时间。因而,传输一个由多个块组成的文件的时间取决于磁盘传输速率。
如果寻址时间约为10ms,而传输速率为100MB/s,为了使寻址时间仅占传输时间的1%,我们要将块大小设置约为100MB。默认的块大小实际为64MB,但是很多情况下HDFS使用128MB的块设置。
块的大小:10ms*100*100M/s = 100M
寻址也就是它得找到要把这个数据存到哪一个block中的时间为10ms,假设寻址时间为10秒,你要存的东西为1kb这样是不是很得不偿失呢?,经过很多测试最佳状态为使寻址时间仅占传输时间的1%,所以为了尽可能的达到这样的效果就需要加大块的大小,当块为100兆,寻址时间一般为10ms这样就达到了最佳的效果,而128又是最近2的次方,所以选128为块的大小.
Hadoop启动停止方式
1)各个服务组件逐一启动
(1)分别启动hdfs组件
hadoop-daemon.sh start|stop namenode|datanode|secondarynamenode
(2)启动yarn
yarn-daemon.sh start|stop resourcemanager|nodemanager
2)各个模块分开启动(配置ssh是前提)常用
(1)整体启动/停止hdfs
start-dfs.sh
stop-dfs.sh
(2)整体启动/停止yarn
start-yarn.sh
stop-yarn.sh
3)全部启动(不建议使用)
start-all.sh
stop-all.sh
配置集群常见问题
1)防火墙没关闭、或者没有启动yarn
INFO client.RMProxy: Connecting to ResourceManager at hadoop108/192.168.10.108:8032
2)主机名称配置错误
3)ip地址配置错误
4)ssh没有配置好
5)root用户和atguigu两个用户启动集群不统一
6)配置文件修改不细心
7)未编译源码
Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
17/05/22 15:38:58 INFO client.RMProxy: Connecting to ResourceManager at hadoop108/192.168.10.108:8032
8)datanode不被namenode识别问题
Namenode在format初始化的时候会形成两个标识,blockPoolId和clusterId。新的datanode加入时,会获取这两个标识作为自己工作目录中的标识。
一旦namenode重新format后,namenode的身份标识已变,而datanode如果依然持有原来的id,就不会被namenode识别。
解决办法,删除datanode节点中的数据后,再次重新格式化namenode。
9)不识别主机名称
java.net.UnknownHostException: hadoop102: hadoop102at java.net.InetAddress.getLocalHost(InetAddress.java:1475)at org.apache.hadoop.mapreduce.JobSubmitter.submitJobInternal(JobSubmitter.java:146)at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1290)at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1287)at java.security.AccessController.doPrivileged(Native Method)at javax.security.auth.Subject.doAs(Subject.java:415) |
解决办法:
(1)在/etc/hosts文件中添加192.168.1.102 hadoop102
(2)主机名称不要起hadoop hadoop000等特殊名称
10)datanode和namenode进程同时只能工作一个。
11)执行命令 不生效,粘贴word中命令时,遇到-和长–没区分开。导致命令失效
解决办法:尽量不要粘贴word中代码。
12)jps发现进程已经没有,但是重新启动集群,提示进程已经开启。原因是在linux的根目录下/tmp目录中存在启动的进程临时文件,将集群相关进程删除掉,再重新启动集群。