YARN 实践记录

HDFS 看护程序:NameNode,Secondary NameNode,和 DataNode
其中NameNode是主看护程序,管理维护着HDFS命名空间元数据,包括文件名,目录名,文件许可,目录许可,
文件到块的映射关系,块ID,以及块在RAM里的位置信息等。

NameNode将元数据信息保存在NameNode的本地文件系统的一个名为fsimage的文件里,平时保持在RAM里来提高快速访问。
保存的命名空间状态不包括块位置信息,块位置信息在NameNode启动时加载到内存中,块的位置信息是由DataNode发送来的块列表构建而成的。
DataNode块列表会在数据节点注册时和运行以后周期的给NameNode。

NameNode不会直接读写HDFS,当一个客户端请求读一个文件时,NameNode提供文件所在块位置给客户端,客户端会直接根据块位置去读取文件。
一个客户端创建一个新文件是,NameNode提供一份按照离客户端远近排序的块位置列表给客户端,客户端会直接将文件写入块中。

NameNode同时会保存一个HDFS命名空间下发生的所有事务的编辑日志文件。
比如创建文件,删除文件,创建块副本等。
该日志文件保存在NameNode的本地文件系统中,名为EditLog, 在NameNode RAM里的修改信息会周期性的写入到该编辑日志文件里。
在NameNode启动时,它会进入安全模式,在此模式下,编辑日志会应用到fsimage来创建一个新的fsimage文件,并保存。
当NameNode退出安全模式后,将会有一个空的编辑文件供其使用。

第二NameNode也会将编辑日志作为其周期检测点。。

CDH5的配置文件core-default.xml 有一个配置项fs.defaultFS 
<property>
    <name>fs.defaultFS</name>
    <value> hdfs://<namenode host>:<namenode port>/</value>
</property>

在hdfs-site.xml配置文件中,dfs.permissions.superusergroup 配置项里来配置HDFS的超级用户
<property>
    <name>dfs.permissions.superusergroup</name>
    <value>hadoop</value>
</property>
在hdfs-site.xml还可以通过dfs.namenode.name.dir属性来指定fsimage文件和编辑日志文件的存放位置:
<property>
    <name>dfs.namenode.name.dir</name>
    <value>/data/1/dfs/nn,/nfsmount/dfs/nn</value>
</property>
至少要配置两个位置,最好一个位置是在NFS 挂载上。

我们还可以通过dfs.namenode.http-address 来为NameNode指定Web用户界面的HTTP 地址。
<property>
    <name>dfs.http.address</name>
    <value>0.0.0.0:50070</value>
</property>

Single Point Of Failure (SPOF)单点故障,如果出现故障只能等NameNode节点恢复才能正常使用。
HDFS高可用性开启后,Secondary NameNode会被启用。

Secondary NameNode
因为所有改变HDFS命名空间的文件修改都会被保存在日志文件中,该文件只会在NameNode启动时被检查一次,
编辑日志文件会在NameNode运行期间变的很大占据额外的硬盘空间,造成在NameNode启动或者检出日志文件到
fsimage过程变得很耗时,延缓NameNode进入功能模式。

Secondary NameNode的功能是在NameNode运行过程中将编辑日志周期性的检出到fsimage文件中。
检出日志文件后,它会清空它,从而使其在NameNode上尽量少的占用磁盘空间。
这样在NameNode启动过程中,就不会在将编辑日志检出到fsimage镜像过程占用太多时间,NameNode的启动就会快很多。

Secondary NameNode使用hdfs-default.xml的dfs.namenode.checkpoint.period来配置检出周期。
默认值为3600秒(1小时),如果配置了dfs.namenode.checkpoint.txns属性,则会覆盖dfs.namenode.checkpoint.period
,该属性指定事务数量,默认为1000000。Secondary NameNode会周期性的去NameNode上检查为迁出事务,这个周期是配置在
dfs.namenode.checkpoint.check.period项上,默认值为60秒。
当一个检出点产生后,Secondary NameNode会从NameNode上下载fsimage文件和编辑日志文件把它们临时保存到
由 hdfs-default.xml配置文件中dfs.namenode.checkpoint.dir属性和dfs.namenode.checkpoint.edits.dir属性指定的目录下。
这两个属性的默认值是file://${hadoop.tmp.dir}/dfs/namesecondary

dfs.namenode.num.checkpoints.retained属性则指定了这些文件拷贝可保存的数量。默认为2个。
在NameNode和SecondNameNode直接传输镜像文件的最大带宽数可以通过hdfs-default.xml文件中的dfs.image.transfer.bandwidthPerSec属性来设置。
0代表不可用。限制镜像传输带宽来保证NameNode执行标准操作。
dfs.image.transfer.timeout属性用于设置镜像传输超时范围,默认值为600000微秒(10分钟)。

NameNode启动时会将编辑日志的一个检出点应用到fsimage文件。NameNode启动时的检出点是基于保存在编辑日志文件里的一定数量的事务。
但是保存在编辑日志文件里的事务数量并不能准确的反应前一个未检出点的事务。
一些额外的事务会保存到由dfs.namenode.num.extra.edits.retained属性指定的事务数量
默认值为1000000,影响额外编辑日志保存的另一个属性是dfs.namenode.max.extra.edits.segments.retained它指定额外日志片段保存数量,默认是10000,
如果设置在dfs.namenode.num.extra.edits.retained的额外事务数量让额外编辑片段超出了dfs.namenode.max.extra.edits.segments.retained设置的数值
那么系统会采用后者的数值来限制额外事务的存储。

Secondary NameNode在加载fsimage文件或者应用编辑日志时可能发生失败的情况,失败后它会尝试重新执行,
尝试次数由 dfs.namenode.checkpoint.max-retries属性设置,默认值为3次尝试。

关于第二命名节点的配置:
将Secondary NameNode主机名添加到conf/slaves文件中,并为Secondary NameNode设置要连接来进行检出操作的NameNode地址。
这些需要在Secondary NameNode节点上的设置 dfs.namenode.http-address

<property>
    <name>dfs.namenode.http-address</name>
    <value><namenode.host.address>:50070</value>
</property>

如果NameNode失去了其所有的fsimage文件和日志文件,则可以使用如下指令来动dfs.namenode.checkpoint.dir目录下
导入最新的检出点内容。
hadoop namenode -importCheckpoint


DataNode看护程序:
存储HDFS数据的奴隶看护程序,数据会被分成块并保存到DataNode上。
块会按照复制因子设置的数值进行复制保存,该因子设置在hdfs-default.xml文件的dfs.replication属性里。
默认值为3,块的大小设置属性是dfs.blocksize,默认值为128M
HDFS块是底层DataNode文件系统的抽象。DataNode存储块的目录在dfs.datanode.data.dir属性里配置。

<property>
    <name>dfs.datanode.data.dir</name>
    <value>/data/1/dfs/dn,/data/2/dfs/dn,/data/3/dfs/dn</value>
</property>

默认情况下,任何数据存储卷出错,DataNode都会关闭,但是我们可以通过dfs.datanode.failed.volumes.tolerated 属性
设置一个失败存储卷的数量来触发DataNode关闭,其默认值为 0
<property>
    <name>dfs.datanode.failed.volumes.tolerated</name>
    <value>1</value>
    <final>true</final>
</property>

DataNode默认情况下会每过3秒跟NameNode进行一次周期性的交互,并周期性的想NameNode进行块信息报告。
在每次块信息报告中,DataNode报告有哪些块副本,哪些块副本出现问题等。
NameNode会为缺少的创建块副本,去掉超出的块副本。如果任何块副本出现了崩溃,那么它会从未崩溃的块副本哪里创建一个新的副本,并
将崩溃的副本移除,必要情况下更新NameNode命名空间元数据。
DataNode也会周期性扫描数据块,看哪些出现了崩溃。
在NameNode启动的安全模式阶段,DataNode的报告会被评估确定是否有足够数量的复制块可用来进如完全功能状态。
如果没有足够的块复制在DataNode上,NameNode会创建它们。
在客户端读取或者写入数据时,NameNode获取数据可以读取的块位置,或者新数据可以添加的位置,并将这些块位置信息发送给客户端。
客户端会直接从DataNode上读取或者写入数据。
客户端使用RPC协议跟DataNode交互,DataNode的Web UI地址通过如下属性配置
<property>
    <name>dfs.datanode.http.address</name>
    <value>0.0.0.0:50070</value>
</property>
DataNode服务器的数据传输地址配置项是:dfs.datanode.address,如果端口是0,则服务在一个自由节点上。
<property>
    <name> dfs.datanode.address </name>
    <value> 0.0.0.0:50010 </value>
</property>

并不是DataNode上所有的空间都要用到HDFS上,为了系统的稳定,推荐在DataNode上预留一部分空间给非dfs使用。
在hdfs-default.xml文件中的dfs.datanode.du.reserved属性可以配置它,默认为0
<property>
    <name>dfs.datanode.du.reserved</name>
    <value>1073741824</value>
    <final>true</final>
</property>

DataNode使用多线程来进行数据进出的传输,我们可以为其配置使用的线程数:
dfs.datanode.max.transfer.threads,其默认值为4096

dfs.namenode.stale.datanode.interval用于设置一个DataNode不跟NameNode进行交互的时间间隔,以确定节点陈旧。
该默认的时间为30000msec(30秒)
如果要避免对陈旧节点的读取,dfs.namenode.avoid.read.stale.datanode设置为true,默认为false
如此会将陈旧节点添加到读取列表的尾部发给请求客户端。
如果避免向陈旧节点写入,则可以设置dfs.namenode.avoid.write.stale.datanode为true,默认也是false,
如果出现陈旧节点太多,又要避免吸入陈旧节的,而可写入节点又很少,
可以设置dfs.namenode.write.stale.datanode.ratio 来指定在陈旧节点达到多大比率时避免对其进行写入操作。
其默认值为0.5f

默认情况下,NameNode会继续提供陈旧DataNode的块位置给请求客户端。
当NameNode请求增加新的块位置来给新文件写入时,会跨节点来为新块选择DataNode节点来平衡硬盘空间使用。
如果集群的所有DataNode都参与硬盘空间利用率平衡,块存储会循环分配。

=====================================
MapReduce看护程序:
两个版本,MR1和YARN(MR2)
MR1的看护程序是JobTracker和TaskTracker
JobTracker负责管理任务和资源,客户端提交MR任务给JobTracker,它会调度并管理任务在TaskTracker上运行。
JobTacker从NameNode上获取数据块位置信息,然后调度任务到邻近数据块的TaskTracker上运行。

TaskTracker负责为MR应用程序运行Map和Reduce任务。每个TaskTracker都是由多个运行任务的插槽组成。
这些插槽slots都是专门定制用于执行Map或者Reduce任务的。TaskTracker根据JobTracker指令来执行Map或者Reduce任务,
执行完成后通知JobTracker。

MR2架构YARN 将MR1的JobTacker分拆为ResourceManager和ApplicationMaster两个独立的看护程序。
Hadoop Components:NameNode,DataNode,ResourceManager,NodeManager,History Server。

ResourceManager:是集群主节点,负责接收客户端提交的任务,并启动ApplicationMaster进程来运行这些任务。
同时,它负责为任务分配可使用的运行资源。客户端提交的任务可以是MapReduce任务,也可以是非MapReduce任务。
ResouceManager由两个独立的组件构成,Schedular和ApplicationsManager
Schedular只是一个资源调度器负责分配运算资源,不参与任何任务的执行和监控工作。
运算资源按照资源容器来分配,每个资源容器都被分配特定的内存。
ApplicationsManager负责接收客户端的任务提交,启动ApplicationMaster来运行这些任务。
它还负责重启那些失败的ApplicationMaster。
ApplicationMaster则是跟应用程序绑定的,每个应用程序都有自己特定的ApplicationMaster。
ApplicationsManager获取了运行ApplicationMaster所需资源后就会启动一个应用程序,
ApplicationMaster根据需要直接从ResourceManager的Schedular获取所需的其它的资源。

NodeManager:集群节点上每台机器都会有一个该看护程序运行。它负责运行ApplicationMaster申请到的资源容器并监控运行在该容器里的应用程序的资源使用情况。
它需要将检测到的资源使用情况报告给ResourceManager,当ApplicationMaster启动/停止 或者监控一个运行在资源容器里的应用程序时,
它其实是通过NodeManager来完成这些工作的。

任务HistoryServer:用于保存提交给Hadoop集群的MapReduce任务的相关信息。
 http://localhost:19888/jobhistory
===================================================================

Apache Hadoop的安装和环境设置:
1、创建目录/cdh并设置全局权限
mkdir /cdh
chmod -R 777 /cdh
cd /cdh
2、创建一个名为hadoop的用户组并添加一个hadoop的用户
groupadd hadoop
useradd -g hadoop hadoop
3、下载安装JDK到/cdh目录
tar zxvf jdk-7u55-linux-i586.gz
4、下载CDH5.4.7 Hadoop 2.6.0
wget http://archive-primary.cloudera.com/cdh5/cdh/5/hadoop-2.6.0-cdh5.4.7.tar.gz
tar -xvf hadoop-2.6.0-cdh5.4.7.tar.gz
5、由于CDH5打包和内建引用的需要,我们需要创建系统链接 symlink
ln -s /cdh/hadoop-2.6.0-cdh5.4.7/bin  /cdh/hadoop-2.6.0-cdh5.4.7/share/hadoop/mapreduce1/bin
ln -s /cdh/hadoop-2.6.0-cdh5.4.7/etc/hadoop  /cdh/hadoop-2.6.0-cdh5.4.7/share/hadoop/mapreduce1/conf

这里symlink只是一个从一个目录指向另一个目录的指针,暗示着当一个特定目录被指针引用时,该目录被调用。
上面的例子中当目录/cdh/hadoop-2.6.0-cdh5.4.7/bin被引用或者调用时,目录/cdh/hadoop-2.6.0-
cdh5.4.7/bin 将被引用或者调用。
同理当目录 /cdh/hadoop-2.6.0-cdh5.4.7/share/
hadoop/mapreduce1/conf被引用时,目录 /cdh/hadoop-2.6.0-cdh5.4.7/etc/hadoop会被调用。

6、我们还需要为hadoop和Java设置环境变量。
我们设置HADOOP_NAMENODE_USER运行NameNode,HADOOP_DATANODE_USER运行DataNode。
我们将基于MR1的MapReduce应用运行 环境变量设置到MR1目录下,将基于YARN的MapReduce应用,
设置到MR2目录下。
vi ~/.bashrc
export HADOOP_PREFIX=/cdh/hadoop-2.6.0-cdh5.4.7
export HADOOP_CONF=$HADOOP_PREFIX/etc/hadoop
export JAVA_HOME=/cdh/jdk1.7.0_55
export HADOOP_MAPRED_HOME=/cdh/hadoop-2.6.0-cdh5.4.7/share/hadoop/mapreduce1
export HADOOP_HOME=/cdh/hadoop-2.6.0-chd5.4.7/share/hadoop/mapreduce1
export HADOOP_CLASSPATH=$HADOOP_HOME/*:$HADOOP_HOME/lib/*:$JAVA_HOME/lib/*
export PATH=/usr/lib/qt-3.3/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:$HADOOP_HOME/bin:$HADOOP_MAPRED_HOME/bin:$JAVA_HOME/bin
export CLASSPATH=$HADOOP_CLASSPATH
export HADOOP_NAMENODE_USER=hadoop
export HADOOP_DATANODE_USER=hadoop

:wq  保存vi编辑bash文件
-----------------------------------------------------------
#User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

#Source global definitions
if [ -f /etc/bashrc ]; then
    ./etc/bashrc
fi
export HADOOP_PREFIX=/cdh/hadoop-2.6.0-cdh5.4.7
export HADOOP_CONF=$HADOOP_PREFIX/etc/hadoop
export JAVA_HOME=/cdh/jdk1.7.0_55
export HADOOP_MAPRED_HOME=/cdh/hadoop-2.6.0-cdh5.4.7/share/hadoop/mapreduce1
export HADOOP_HOME=/cdh/hadoop-2.6.0-chd5.4.7/share/hadoop/mapreduce1
export HADOOP_CLASSPATH=$HADOOP_HOME/*:$HADOOP_HOME/lib/*:$JAVA_HOME/lib/*
export PATH=/usr/lib/qt-3.3/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:$HADOOP_HOME/bin:$HADOOP_MAPRED_HOME/bin:$JAVA_HOME/bin
export CLASSPATH=$HADOOP_CLASSPATH
export HADOOP_NAMENODE_USER=hadoop
export HADOOP_DATANODE_USER=hadoop

:wq

------------------------------------------------------------------------
7、检查设置的环境变量
echo $PATH

========================================================================
Hadoop 集群模式
支持三种集群模式,standalone,pseudo-distributed和fully-distributed
单点模式:作为一个单一java进程(JVM)运行。该模式是非分布式,所以HDFS不可用。
而是使用本地文件系统存储。

伪分布式模式:
所有组件单独运行在同一个节点的不同JVM上,实质上是在单节点上运行多个JVM进程。

完全分布式模式:
Hadoop运行在真正集群上,该集群有多个节点,从2、3到几百上千个节点。
-----------------------------------------------------------------
在单点模式下执行一个基于MR1的应用程序:
1、创建一个工作目录
mkdir /cdh/input
2、拷贝Hadoop所有配置文件到该目录
cp $HADOOP_CONF/*.xml /cdh/input
3、运行命令查看拷贝结果
ls -l
4、运行打包在hadoop-example-2.6.0-mr1-cdh5.4.7.jar里的Grep任务
hadoop jar $HADOOP_HOME/hadoop-examples-2.6.0-mr1-cdh5.4.7.jar grep /cdh/input/ /cdh/output 'dfs[a-z.]+'
5、显示输出内容
ls -l /cdh/output/*
6、查看结果文件
vi /cdh/output/part-00000


字母统计实例运行:
1、将WordCount.java文件从例子目录拷贝到 /cdh
cd /cdh
cp /cdh/hadoop-2.6.0-cdh5.4.7/src/hadoop-mapreduce1-project/src/examples/org/apache/
hadoop/examples/WordCount.java
2、编译该Java源文件
hadoop com.sun.tools.javac.Main WordCount.java
3、打包编译后的.class 文件成.jar文件
jar cf wordcount.jar WordCount*.class
4、我们需要创建一个数据集作为统计输入,/cdh/input/input1.txt
------------------------------------------------------------
伪分布式模式下运行MR1
MR1框架可以将一个MapReduce任务作为一个本地进程运行,让Map/Reduce任务运行在单个JVM上。
或者作为一个分布式进程,Map/Reduce任务运行在TaskTracker插槽,由JobTracker来管理该任务。

默认情况下,如果我们将mapred-site.xml文件中的mapreduce.framework.name 值设置为local,则
Map/Reduce任务运行在本地单一JVM上。如果设置为classic,则会分开在JobTracker和TaskTracker组件上,
这一般是伪分布式或者全分布式模式。在这种模式下,需要设置JobTracker的URI属性mapreduce.jobtracker.address,其默认值为local.
如果在MR2框架下,则需要将mapreduce.framework.name值设置为yarn。

在伪分布式模式下,我们需要配置Hadoop内核和HDFS属性,在core-site.xml文件中指定NameNode URI,
fs.defaultFS 和 Hadoop在进行Map/Reduce处理过程中使用的目录 hadoop.tmp.dir的值。
不同的安装版本和网络配置决定了URI的不同。
hdfs://localhost:8020
/var/lib/hadoop-0.20/cache


vi $HADOOP_CONF/core-site.xml
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->mk
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://10.0.2.15:8020</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/var/lib/hadoop-0.20/cache</value>
</property>
</configuration>

:wq
------------------------------------------
步骤:
1、创建需要设置的目录,如果已有需要先删除
rm -rf /var/lib/hadoop-0.20/cache
mkdir -p /var/lib/hadoop-0.20/cache
chmod -R 777 /var/lib/hadoop-0.20/cache

2、在 hdfs-site.xml中配置HDFS,比如设置NameNode存储目录 dfs.namenode.name.dir
因为伪分布式模式运行在单机上,我们需要修改默认的复制因子从3改为1,并设置dfs.replication属性。
还需要设置HDFS的超级用户组属性dfs.permission.superusergroup为hadoop
将dfs.permissions设置为false关闭许可检查,否则mode,owner和group都会被检查。
vi $HADOOP_CONF/hdfs-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>dfs.permissions.superusergroup</name>
<value>hadoop</value>
</property><property>
<name>dfs.namenode.name.dir</name>
<value>/data/1/dfs/nn</value>
</property>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
</configuration>

:wq


vi /cdh/input/input1.txt

:wq
vi /cdh/input/input2.txt

:wq
5、在执行之前,移除上一次执行使用的配置文件*.xml
cdh/input> rm *.xml
6、运行全限定名应用程序
hadoop jar wordcount.jar org/apache/hadoop/examples/WordCount /cdh/input /cdh/output
7、查看输出文件
ls -l /cdh/output
8、查看结果文件内容
vi /cdh/output/part-r-00000
=============================================================================================
YARN上的资源分配
Yet Another Resource Negotiator,在MRv2架构下对集群资源管理来说是一个决定性的组件。原来MRv1的JobTracker的功能被委托给
JobHistory Server(负责任务完成状态记录),ResourceManager(集群资源管理),和一个或者多个ApplicationMaster(MapReduce处理进程)
在MRv1中基本的资源单元是一个TaskTracker slot插槽,它被指定为特定的处理任务类型,map或者reduce任务,不能混用。
在MRv2种TaskTracker被NodeManager替代,参与资源分配的是ResourceManager和每个节点上运行的NodeManager.
ResourceManager只运行在集群的主节点上,负责全局资源的调度,可以为不同的应用程序调度和配置资源。
NodeManager运行在从属节点上,负责跟ResourceManager进行交互。

资源的基本单位也不再是MRv1的slot 插槽,而是被抽象为container, 资源的一个container会包含内存和CPU。
每个集群节点上可用的的内存和CPU需要在yarn-site.xml文件的yarn.nodemanager.resource.memory-mb和yarn.nodemanager.resource.cpu-vcores属性设置。
可分配给所有container的默认内存值为8192MB,默认可以分配给所有container的CPU内核数是8个。

节点的虚拟内核提供了多线程,虚拟内核又受限于节点的物理内核数量。
虚拟内核和内存是以散列块形式提供给container,而不是任意值。
yarn.scheduler.minimum-allocation-mb 设置了可以分配给一个container的最小内存数。
其默认值为1024MB。yarn.scheduler.increment-allocation-mb设置了递增量,默认为 1MB。
yarn.scheduler.minimum-allocation-vcores 设置了分配给一个container的最小内核数,默认值为 1
yarn.scheduler.increment-allocation-vcores 设置递增量,默认值是 1
yarn.scheduler.maximum-allocation-mb 设置可分配给一个container的最大内存值,默认为8192MB
yarn.scheduler.maximum-allocation-vcores 设置可分配给一个container的最大内核数,默认为32
内核每次增加数必须是yarn.scheduler.increment-allocation-vcores的倍数。

ApplicationMaster,Map和Reduce任务都是运行在Container中的。
ApplicationManager可使用的内存数和CPU虚拟内核数是由下面yarn-site.
xml文件中两个属性设置的:
yarn.app.mapreduce.am.resource.mb 默认值为1536
yarn.app.mapreduce.am.resource.cpu-vcores 默认值为 1

每个Map任务需要的vunei内核数设置在mapred-site.xml文件中:
mapreduce.map.cpu.vcores 默认为 1
每个Reduce任务需要的内存数设置:
mapreduce.reduce.cpu.vcores 默认值为 1

一个NodeManager可以有多个container,其可用资源分配给每个container
但是同一个节点上的多个container分配到的资源数是不一样的。
ApplicationMaster会运行在独立的container上。

Container由ResourceManager根据应用程序的请求来创建。
一个节点上的所有container资源的综合不能超出节点本身的容量。
每个container负责运行一个独立的任务(map或者reduce),在一个任务结束后可以运行另外一个不同类型的任务。

每个应用程序都会启动一个对应的ApplicationMaster,它运行在一个container里。
ApplicationMaster可能会请求更多的container来运行MapReduce任务,这些任务可以在不同的容器中同时运行,可以是不同节点上。

当ResourceManager接收到客户端请求运行一个应用程序时,它首先为ApplicationMaster创建一个Container并通过NodeManager来在其中运行ApplicationMaster。
接着ApplicationMaster会向ResourceManager请求额外的资源运行应用程序,ResourceManager会将分配的container ID发送给ApplicationMaster
NodeManager负责加载任务到这些容器。
当一个应用程序运行结束,ResourceManager会收回分配给它的Container。
收回的Container会后续的分配给其它不同的ApplicationMaster来运行其它应用程序。
因为Container不是固定的运行某种类型的,所以同一个container可以运行map和reduce

NodeManager在注册到ResouceManager时会提供该节点的可用资源情况给ResourceManager。
NodeManager管理者container运行进程,其中包括运行ApplicationMaster
的进程。 NodeManager启动ApplicationMaster,ApplicaitonMaster向ResourceManager请求后续任务运行的
资源,然后在相应的NodeManager上启动任务执行。
NodeManager通过在HDFS上的集中日志为应用程序提供日志服务。
NodeManager会运行一些其它辅助程序以及通过ACLs来管理哪个用户可能提交的应用程序。

在ApplicationMaster启动以后,它会向ResourceManager发送一个资源请求,ResourceManager会将分配的资源以Container的形式通知给ApplicationMaster。

关于一个节点上的内存分配问题:
假设一个节点有90GB的RAM和4-hex 内核(24 核)CPUs。每个内核提供给一到两个container来计算,
该节点大约能提供40个container. 90GB的内存预留10GB给操作系统,YARN将有80GB可用。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property>
    <name>yarn.nodemanager.resource.memory-mb</name>
    <value>81920</value>
</property>
<property>
    <name>yarn.scheduler.minimum-allocation-mb</name>
    <value>2048</value>
</property>
<property>
    <name>mapreduce.map.memory.mb</name>
    <value>4096</value>
</property>
<property>
    <name>mapreduce.reduce.memory.mb</name>
    <value>4096</value>
</property>
<property>
    <name>mapreduce.map.java.opts</name>
    <value>-Xmx3072m</value>
</property>
<property>
    <name>mapreduce.reduce.java.opts</name>
    <value>-Xmx3072m </value>
</property>
这里配置yarn的可用内存资源为80G,配置40个container,那么每个container的最小内存数是2GB
配置4GB给map任务,4GB给reduce任务。每个container都要为一个map/reduce任务运行一个JVM
给JVM设置的heap大小必须小于该map/reduce任务的内存限制,这里我们设置为3GB。
JVM heap大小限制的是可用物理内存大小,虚拟内存(物理和分页)可用大小则是通过yarn-site.xml文件中的
yarn.nodemanager.vmempmem-ratio 设置,其默认为 2.1,它代表container可用的虚拟内存和物理内存的比例。

<property>
    <name>yarn.nodemanager.vmem-pmem-ratio</name>
    <value>2.1</value>
</property>

YARN 支持公平调度和FIFO调度,其中公平调度是默认值。容量调度是从MRv1就有的,
公平调度支持层级序列,运行序列有其子序列,它们共享分配给该父序列的资源。

<?xml version="1.0"?>
<allocations>
    <queue name="user1">
        <minResources>1024 mb,1vcores</minResources>
        <maxResources>4096 mb,3vcores</maxResources>
        <maxRunningApps>20</maxRunningApps>
        <aclSubmitApps>hdfs,admin</aclSubmitApps>
        <weight>1.0</weight>
        <schedulingPolicy>fair</schedulingPolicy>
        <queue name="user1-sub">
            <aclSubmitApps>root</aclSubmitApps>
            <minResources>512 mb,1vcores</minResources>
        </queue>
    </queue>
    <user name="root">
        <maxRunningApps>20</maxRunningApps>
    </user>
    <user name="hdfs">
        <maxRunningApps>10</maxRunningApps>
    </user>
    <user name="admin">
        <maxRunningApps>5</maxRunningApps>
    </user>
    <userMaxAppsDefault>5</userMaxAppsDefault>
    <fairSharePreemptionTimeout>60</fairSharePreemptionTimeout>
</allocations>
上面是公平调度机制的配置文件,包括如下几个元素:
<user/>  
<userMaxAppsDefault/> 指定每个用户运行的最大应用程序默认数
<fairSharePreemptionTimeout/> 指定一个序列在公平共享从其它序列优先获取资源等待的秒数
<defaultQueueSchedulingPolicy/> 指定使用的调度策略,具体用户的schedulingPolicy设置将覆盖全局设置。

minResources:为一个序列设置最小资源数,是以内存数和虚拟内核数组合形式设置: "512MB,1 vcores"
maxResources:为一个序列设置最大资源数,是以内存数和虚拟内核数组合形式设置:"2048MB,6 vcores"
maxRunningApps:从一个序里同时运行的最大应用程序数
weight: 为一个序列指定可用和同一集群其它序列共享的权重,默认为1
schedulingPolicy:指定使用的调度政策,"fifo"/"fair"/"drf",默认为”fair“
aclSubmitApps:指定可以向序列提交应用的用户
minSharePreemptionTimeout:指定秒数后,序列会抢占该容器资源的其它序列的最小份额

----------------------------------------------------------------------
MapReduce在YARN上运行的工作流程:
1、客户端从ResourceManager上获取应用程序ID
2、客户端提交应用程序给ResourceManager
3、ResourceManager启动ApplicationMaster和一个NodeManager来运行应用程序
4、ApplicationMaster注册自己到ResourceManager
5、ApplicationMaster从ResourceManager请求容器资源
6、ResourceManager发送容器资源信息给ApplicationMaster
7、ApplicationMaster发送请求给拥有容器的NodeManager来启动分配到的容器资源
8、NodeManager启动容器资源并启动附加到该容器资源上的任务执行
9、NodeManager发送一个资源容器状态报告和任务运行状况给ApplicationMaster
10、当一个资源容器完成一个任务的运行后,ApplicationMaster请求NodeMaster来关闭该容器。
11、NodeManager关闭该资源容器。
12、ApplicationMaster通知ResourceManager这次执行结果(成功或者失败)

客户端可以直接从ResourceManager或者ApplicationMaster获取处理结果和运行状态。
NodeManager周期性的发送节点状态给ResourceManager

客户端使用ApplicationClientProtocol协议和ApplicationClientProtocol#getNewApplication(GetNewApplicationRequest request)方法
从ResourceManager 获取应用程序ID,ResourceManager发送全局唯一增加的应用程序ID给客户端
客户端运行在自己的JVM上。

客户端使用ApplicationClientProtocol#submitApplication(SubmitApplicationRequest request)向ResourceManager提交应用程序。
在SubmitApplicationRequest中会包含序列信息以及以内存和CPU描述的资源需求信息。
资源信息类 org.apache.hadoop.yarn.api.records.Resource
ResourceManager会返回org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationResponse 
此时该回复是空的不包含任何关于应用程序是否提交成功和启动信息。
客户端需要接下来通过getApplicationReport(GetApplicationReportRequest request)方法获取应用程序报告。
ResourceManager 会为其返回GetApplicationReportResponse对象,该对象包含ApplicationReport,应用程序名称,ApplicationMaster运行的主机,
ApplicationMaster的RPC端口,应用程序开始时间,跟踪URL,以及应用程序状态等信息。
在客户端提交一个应用程序前,客户端会拷贝资源到HDFS。

ResourceManager加载一个ApplicationMaster来在一个节点上运行应用程序。
ResourceManager的ApplicationManager组件请求NodeManager启动第一个容器来运行ApplicationMaster,
NodeManager启动ApplicationMaster容器。在ApplicationMaster失败时ApplicationManager负责重启它。
ApplicationMaster是一个MapReduce应用程序专有的框架。

ApplicationMaster使用ApplicationMasterProtocol.registerApplicationMaster(RegisterApplicationMasterRequest request)
方法注册资金到ResourceManager。ResourceManager回复RegisterApplicationMasterResponse对象,它包含集群中最大可分配的资源容量。

ApplicationMaster用ApplicationMasterProtocol.allocate(AllocateRequest request)方法
从NodeManager请求容器资源使用,返回AllocateRequest对象包含进度信息,应用程序需要的ResourceRequest列表,
和未使用容器列表。
ResourceRequest包含请求优先级,机器名称 或者机架编号,用*则表示任意主机/机架
一份资源描述应该包括内存(MB)和/或者 CPU

ResourceManager使用AllocateResponse发送容器资源给ApplicationMaster。
AllocateResponse包含新分配的容器列表,已完成的容器状态列表,已被更新的节点列表,
集群中可用的节点列表,被集群请求的资源描述,用于让ApplicationMaster直行一些行为的指令AMCommand
比如resync 或者 shutdown。
在集群上表示被分配的资源容器包括的信息由ContainerId,NodeId,以及分配给容器的Resource。

ApplicationMaster使用ContainerManagementProtocol协议和ContainerManagementProtocol.startContainer(StartContainerRequest request)方法
发送请求给NodeManager来启动分配到的容器资源。请求中包含分配到的资源容量,在容器中运行任务需要进行的环境配置,
运行容器的指令。 NodeManager返回StartContainersResponse对象,我们可以使用getSuccessfullyStartedContainer方法从该对象中
获取成功启动的容器列表。

NodeManager启动容器并将任务JVM付给容器,任务执行JVM从HDFS获取应用程序资源,容器发送任务执行的MapReduce状态给NodeManager。

当ApplicationMaster使用ContainerManagementProtocol.getContainerStatuses(GetContainerStatusesRequest request)方法
向NodeManager请求容器和任务运行状态时,NodeManager会返回关于容器和任务运行的状态报告给他。
其回复对象为 GetContainerStatusesResponse,我们可以通过其方法getContainerStatuses()来获取
一个容器的状态列表List<ContainerStatus>

当一个容器的任务运行完成后,ApplicationMaster会请求其所在NodeManager使用ContainerManagementProtocol.stopContainer(StopContainersRequest request)方法
关闭该容器。NodeManager回复StopContainerResponse对象给ApplicationMaster,我们在该对象里使用getSuccessfullyStoppedContainers()方法获取
成功停止的容器列表。

NodeManager停止容器后悔已状态报告的形式通知ApplicationMaster。

ApplicationMaster再使用ApplicationMasterProtocol.finishApplicationMaster(FinishApplicationMasterRequest request)方法通知ResourceManager的ApplicationManager组件关于它的完成情况,
以及从ResourceManager取消注册。

------------------------------------------------------------------------
HDFS 高可用性看护程序

HDFS高可用性看护程序提供了一个备份NameNode来接替失败的活动NameNode。
第二NameNode不使用HDFS高可用NameNode,
HDFS看护程序决定了HDFS HA是否可用。
HDFS HA需要配置,在CDH5默认是不可用的。
HDFS HA的看护程序包括:NameNode,Standby NameNode,JournalNodes,Zookeeper和DataNodes

活动NameNode:
HDFS HA 在活动/被动配置中,有两个NameNode同时运行在集群中。
处于活动状态的NameNode被称为active NameNode,在HA中活动NameNode的功能跟非HA HDFS下的NameNode一样。
硬件配置也都是一样的(HA HDFS下的活动NameNode,非HA HDFS下的NameNode,以及备份NameNode)

备份NameNode:在HDFS HA中被动的NameNode称为 备份NameNode,是一种热备份,如果活动NameNode出现故障或者阻塞,
会自动切换到备份NameNode.
我们需要在hdfs-default.xml配置文件中设置快速容错dfs.ha.automatic-failover.enabled属性设置为true
快速失败恢复意味着备份NameNode自动成为活动NameNode,管理员介入的错误回复可以被用于计划保养。

备份NameNode必须保持足够的状态才能快速故障切换。这就意味着活动NameNode的状态必须同步到备份NameNode上。
在活动NameNode和备份NameNode之间可以通过如下方法进行同步命名空间状态:
基于法定人数存储
使用NFS共享存储
Quorum-based storage ,活动NameNode和备份NameNode使用一个法定数量的JournalNodes交互。
保持一个活动NameNode的编辑日志,备份节点在被记录到JournalNode时读取该编辑日记应用到自己的状态中。
活动NameNode日志写入到法定JournalNode的大部分节点上。

使用NFS共享存储方法,在hdfs-default.xml文件中设置 dfs.namenode.shared.edits.dir 来指定一个共享目录。
用于在这两者之间同步状态。活动NameNode将日志记录到共享目录,备份NameNode读取编辑日志更新自己的命名空间状态。
方法角色的转换,只有一个NameNode是活动的,能够向共享目录写入日志。

备份NameNode使用检出点从共享目录中获取编辑日志应用到自己的fsimage文件,
所以Secondary NameNode在HDFS HA中没必要存在。

JournalNode 日记节点
该看护程序用于活动节点和备份节点基于法定数量存储状态同步中。
活动NameNode和备份NameNode通过法定数量的日记节点来通讯。
在活动NameNode上如果有任何的命名空间修改,其编辑日志就会传到大部分的日记节点上。
一个法定组有多个日记节点,通常是奇数个(odd number),至少有3个。如果有N个日记节点,
则可以容错(N-1)/2,这就是为什么必须保持日记节点数为奇数。
备份NameNode从其中一个日记节点读取编辑日志将它们应用到自己的命名空间修改中来保持其跟活动节点的状态同步。
日记节点任何时候也只允许一个NameNode处于活动状态下。

日志节点看护程序是轻量级的,可以与其他看护程序组合在节点上使用,比如MRv1 JobTracker,NameNode
或者MRv2 ResourceManager

ZooKeeper:
是一个协调看护程序,用于活动NameNode的快速故障恢复到备份NameNode。
它在HA HDFS集群中有两个功能:
判断活动NameNode的失败,每一个活动NameNode和备份NameNode之间都在ZooKeeper中维护一个活动会话,
当活动NameNode失败后,ZooKeeper探测故障作为NameNode会话失败的结果。

ZooKeeper初始化一个故障恢复到备份NameNode并提供一个活动NameNode的遴选机制。

DataNode数据节点看护
在HA和non-HA HDFS下功能一样,在HA下,DataNode会周期性的跟NameNode交互并发送块报告给活动NameNode和备份NameNode
以使他们状态同步

HDFS的好处和挑战:
Hadoop Distributed Filesystem(HDFS)分布式,可扩展,具备容错性能的文件系统
用于存储,处理并提供并行流来访问大量数据,运行在普通商业硬件上。

转载于:https://my.oschina.net/u/924064/blog/903352

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值