栖静林

不忘初心,方得始终


  • 首页

  • 分类

  • 归档

  • 标签

白话Java NIO

发表于 2016-10-07   |   分类于 Java   |     |   阅读次数

目前Java支持的IO共有三种:

名称 支持版本 特点
IO(也叫BIO) JDK 1.0 B=block,阻塞
NIO JDK 1.4 N=new,非阻塞
AIO(NIO2.0) JDK 1.7 A=asynchronous,异步

本文主要通过对比BIO和NIO,尽量通俗易懂的介绍NIO,重在有个整体认识,不深入代码实现,也不讨论同步/异步(因为还没弄懂-_-!。。懂了再补)。

IO

I/O,即input/output,可以说任何端到端的通信,大体都由三部分组成:输入–>传输–>输出。常见的有文件读写、网络通信,都属于IO。

BIO

概念

BIO大家都熟悉,在BIO中:
BIO

  1. 每一个端到端的连接叫Stream,两端的输入输出都是对着Stream进行的
  2. 输入输出面向的是字节(即操作实体、基本单位),每次读写操作都是一个字节一个字节进行的
  3. 从Stream中读数据,是阻塞的,即没有数据时,进行读操作的线程就进入阻塞状态,干不了其他事,直至读到数据为止

应用

以常见的Socket服务器为例:
BIO-Server

  1. 因为监听客户端连接请求的Socket会阻塞,所有单独放在一个线程,无限循环监听
  2. 因为每个客户端连接中使用的Stream读写时会阻塞,又不能相互影响,所以每收到一个连接请求,就单独开一个线程,一对一的负责客户端输入输出

弊端

  1. 阻塞造成的:如果连接较多,而且每个连接(Stream)上的数据量都很小,那么大多数的线程,大部分时间都是处于阻塞状态的(因为没有数据它要干等着啊),所以CPU大部分时间都在忙于线程调度,效率低下
  2. 面向字节造成的:因为每次读写都是一个字节,不仅慢,而且没有任何其他操作的余地,比如数据前后移动、定位等(但这个是可以通过字节数组手动改善的,即每次读写一个字节数组)

适用场景

只要反着上边说的情况,就是它的适用场景:

  • 连接数少,但每个连接上,数据量大

NIO

概念

针对BIO的缺点,在JDK 1.4推出了NIO,主打非阻塞:
NIO

BIO ——————> NIO
Stream ——————> Channel
Byte ——————> Buffer
阻塞 ——————> 阻塞/非阻塞
接头人Stream ——————> 接头人Selector
  1. 每一个端到端的连接,从Stream变成了Channel
  2. 输入输出面向的基本单位,从字节变成了缓冲区(本质就是一个封装好的字节数组)
  3. Channel有阻塞/非阻塞两种模式可选,非阻塞模式下,没有数据时就不用干等着了
  4. 不干等着,又没数据,那能干嘛呢?那就去看看其他Channel有没有数据呗?为了配合Channel的非阻塞模式,新添加了一个Selector,Selector到Channel是一对多的关系,相当于是Channel的管理者。以前数据向Stream要,现在向Selector要,Selector会把已经有数据的Channel挑选准备好,只有所有Channel都没数据时,在Selector这里才会阻塞。所以等于把阻塞的级别提高了一个维度,大大降低了阻塞的可能。可以类比进程和线程的关系:当且仅当一个进程中所有线程都死了,这个进程才算死了。

应用

还以常见的Socket服务器为例:
NIO-Server

  1. 监听客户端连接请求的Socket变成了ServerSocketChannel,设置成非阻塞模式,然后把它交给Selector来管理,并告诉Selector它只负责连接请求,不负责读写,因为不阻塞,所以不用单独开线程
  2. 无限循环,阻塞式地向Selector索要有数据的Channel:
    a. 如果是连接请求来了,那就把新的连接SocketChannel也交给Selector来管理,并告诉Selector它是负责读写数据的
    b. 如果是需要读写的数据来了(即已有的连接),那就进行数据读写处理
    c. 如果当前所有的Channel都没数据,那就在Seletor这里阻塞着,直到至少一个Channel有数据为止
    d. 虽然在Seletor这里也有可能阻塞,但仍不需要单独开线程,就在主线程办。为什么呢?如果Selector阻塞了,说明当前没有什么数据可处理的,都没事干了,主线程阻塞歇着又有何妨呢?

弊端

  1. 排队造成的:什么是排队呢?当多个Channel都有数据时,只有单个线程通过Selector顺序处理它们,不就等于在排队处理吗?那么,如果每个Channel数据量都很大,零并发,效率低下
  2. 以上问题,可以通过增加Selector数量,减小单个Selector管理的Channel量,增加并发度来缓解,但仍存在排队问题,并没有根本解决

适用场景

● 连接数多,但每个连接上,数据量小

这时你可能也发现了,那如果连接数多,每个连接上数据量也大时,以上两个就都不适用了?怎么办呢?——AIO,具体还不懂,就不多说了。

从零爬Hadoop系列_9-各组件相关命令和WebUI使用

发表于 2016-09-26   |   分类于 Hadoop   |     |   阅读次数

本文主要是HDFS、YARN、MR三个组件相关命令和对应的Web UI使用说明,以及相关的配置说明。

HDFS

hdfs-site.xml配置说明

  1. fs.name.dir:这是NameNode结点存储hadoop文件系统信息(fsimage)的本地路径,可以配置多个路径,但这些目录汇总的文件是一样的(防止某个磁盘挂掉,做备份)。Deprecated,use {dfs.namenode.name.dir} instead,当前配置依然生效,向前兼容
  2. dfs.data.dir:hdfs上的数据在本地磁盘的存储路径,如果有多磁盘最好每个磁盘都配置一个路径,这样hdfs会轮询在这些路径中写入数据。所以datanode在dfs.data.dir每一项位置汇总存的数据是不一样的,这个和namenode不同。Deprecated,use {dfs.datanode.name.dir} instead,当前配置依然生效,向前兼容
  3. dfs.replication:设置数据块的复制次数,默认是3。如果大于节点数,则每个节点中都会存一份备份,而不会超过节点数
  4. dfs.namenode.http-address:NM Web UI地址,默认值为0.0.0.0:50070

启动

在etc/hadoop/slave和ssh配置互信的前提下,通过执行sbin/start-dfs.sh启动。之后在master节点通过jps可看到三个进程:DataNode,NameNode,SecondrayNameNode,在slave节点可看到DataNode

停止

同上,通过执行sbin/stop-dfs.sh停止

常用命令

  1. 格式:hadoop fs <-command>(可通过hadoop fs -help [command]查看说明,另外这里主要是hdfs文件操作命令,有关hdfs系统管理命令,如启动datanode等,参考hdfs命令)
  2. 常用的文件操作命令同Linux,如cat、mkdir、ls、rm、mv、cp、find、df、du、chmod、chown、chgrp等
  3. -put <本地路径> <hdfs路径>:文件上传(复制),可多个,用空格分隔,即最后一个参数是hdfs目的路径,前边的都是要上传的本地路径。其中目录路径一定要存在(通过mkdir创建),不然会报错(这点和Linux命令不同,在Linux中,cp命令会自动创建不存在的目的路径并完成复制)
  4. -copyFromLocal <本地路径> <hdfs路径>:和put完全相同
  5. -moveFromLocal <本地路径> <hdfs路径>:剪切本地文件到hdfs,可多个,规则同上
  6. -get <hdfs路径> <本地路径>:文件下载(复制),可多个,规则同上
  7. -copyToLocal <hdfs路径> <本地路径>:和get完全相同
  8. -moveToLocal <hdfs路径> <本地路径>:此命令还未实现,“Option ‘-moveToLocal’ is not implemented yet”

Web UI

  1. 访问地址由配置项dfs.namenode.http-address决定,默认0.0.0.0:50070
  2. 当前如果在浏览器中输入http://m1:50070,并不能正常访问,而是显示了一段html,仔细看得话,其中包含一个跳转语句,跳转到dfshealth.html,但不知道为什么没有跳转,所以需要手动输入地址http://m1:50070/dfshealth.html进行UI访问
  3. 主要功能
    • Overview:所有datanode整体概况,如总容量、已用容量、剩余容量等
    • Datanodes:各个datanode的概况,如总容量、已用容量、剩余容量等(相加等于上一条)
    • Datanode Volume Failures:节点故障
    • Snapshot:文件快照
    • Startup Progress:启动过程中各个阶段的完成情况和耗时
    • Utilities
      • UI查看日志文件
      • UI查看hdfs文件系统

YARN

yarn-site.xml配置说明

  1. yarn.nodemanager.aux-services:NM上运行的附属服务。需配置成mapreduce_shuffle才能运行MR程序
  2. yarn.nodemanager.aux-services.mapreduce.shuffle.class:顾名思义,默认配置为org.apache.hadoop.mapred.ShuffleHandler,如果没有自定义实现,可缺省
  3. yarn.resourcemanager.hostname:RM所在节点的IP,默认值0.0.0.0,可以不用另外配置
  4. yarn.resourcemanager.webapp.address:RM Web UI地址,默认值${yarn.resourcemanager.hostname}:8088,可以不用另外配置

启动

在etc/hadoop/slave和ssh配置互信的前提下,通过执行sbin/start-yarn.sh启动。之后在master节点通过jps可看到两个进程:ResourceManager,NodeManager,在slave节点可看到NodeManager

停止

同上,通过执行sbin/stop-yarn.sh停止

常用命令

  1. yarn resourcemanager:启动RM
  2. yarn nodemanager:在每个slave节点启动一个NM
  3. yarn rmadmin [-options]:RM管理员命令,如刷新队列、刷新节点等
  4. yarn jar <jarFile> [mainClassName] <inputDir> <outputDir>:运行指定的jar文件jarFile,如果打包时指定了mainClass,则[mainClassName]可不指定,否则需要指定,输入数据目录为inputDir,输出数据到目录outputDir
  5. yarn application <-command>:application 相关的命令
    • -list [-options]:列出所有applications,通过options可以筛选
      • -appStates <States>:通过States筛选applications,其中可以是逗号分隔的多个项,有效的States如下:ALL、NEW、NEW_SAVING、SUBMITTED、ACCEPTED、RUNNING、FINISHED、FAILED、KILLED
      • -appTypes <Types>:通过Types筛选applications
    • -kill <ApplicationID>:杀死指定的application
    • -status <ApplicationID>:打印指定application的状态
  6. yarn applicationattempt <-command>:applicationattempt 相关的命令
    • -list <ApplicationID>:列出指定application的所有运行实例applicationattempt
    • -status <ApplicationAttemptID>:打印指定applicationattempt 的状态
  7. yarn container <-command>:container相关的命令
    • -list <ApplicationAttemptID>:列出指定applicationattempt的所有Container
    • -status <ContainerID>:打印指定Container的状态
  8. yarn node <-command>:node相关的命令
    • -list [-options]:默认列出所有正常运行的nodes
      • -all:列出所有nodes,包括不健康的等非正常状态
      • -states <States>:根据states筛选列出对应的nodes
      • -status <NodeID>:打印指定node的状态
  9. yarn queue -status <QeueuName>:打印指定队列的状态,如负载等,但没有对应的获取队列名的命令,只能通过mapred queue -showacls获取queueName
  10. yarn logs -application <applicationID> [-options]:打印指定application的日志
  11. yarn cluster -lnl:list node labels
  12. yarn daemonlog <-command>
    • -getlevel <host:port> <name>:获取指定hadoop守护进程的日志级别
    • -setlevel <host:port> <name> <level>:设置指定hadoop守护进程的日志级别
  13. yarn top:类似Linux的top命令,动态查看集群状态

Web UI

  1. 访问地址由配置项yarn.resourcemanager.webapp.address决定,默认${yarn.resourcemanager.hostname}:8088
  2. 主要功能:
    • Nodes:集群整体的apps概况和资源概况,调度器的配置,以及各个nodes的资源概况
    • Node Labels:查看各个Label的情况,如NM数量、资源总量(Label主要用于一种调度策略Label based scheduling,该策略是apache hadoop2.6.0和hdp2.2引入的,只有Capacity Scheduler支持该特性,其主要思想是:用户可以为每个NM标注几个标签,比如highmeme,highdisk等,以表明该NM的特性,同时用户可以为调度器中每个队列标注几个标签,这样,提交到某个队列中的作业,只会被分配到标注有对应标签的NM上的资源。该特性是为了让YARN更好的运行在异构集群中,更好地管理和调度混合类型的应用程序)
    • Applications:查看各个application的状态,包括开始时间、结束时间、使用的资源量、进度等,其中还可以根据状态分类查看
    • Scheduler:查看调度器的情况,如Container情况、分配情况、抢占情况等
    • Tools
      • UI查看本地日志
      • UI查看RM服务状态

MR

mapred-site.xml配置说明

  1. mapreduce.framework.name:指使用哪种框架来运行任务,三个选项:classic,yarn,local,默认为local
    • classic:任务提交给JobTracker,它的地址通过mapreduce.jobtracker.address配置
    • yarn:任务提交给RM中的applications manager,它的地址通过yarn.resourcemanager.address配置(在yarn-site.xml中)
    • local:任务提交给本地JobTracker,即在本地使用MR,把mapreduce.framework.name和mapreduce.jobtracker.address都配置为local即可
  2. 为了方便用户查看历史作业信息,MRAppMaster提供了一个JobHistory-Server,该服务由四个子服务组成,其中除了负责扫描删除的服务,其他三个服务都是对外的,相关配置如下:
    • mapreduce.jobhistory.webapp.address:Web UI访问地址,默认0.0.0.0:19888
    • mapreduce.jobhistory.admin.address:对外暴露的执行管理员命令的服务接口,通过执行mapred hsadmin输入的命令,都是通过该接口提交执行的,默认0.0.0.0:10033
    • mapreduce.jobhistory.address:JobHistory服务负责从HDFS上读取MR历史作业日志,然后解析成格式化信息,供UI查看,该项即该服务对UI服务进程暴露的IPC接口,默认0.0.0.0:10020

常用命令:

  1. mapred queue <-command>:
    • -list:列出所有队列信息和负载状态
    • -info <job-queue-name> [-showJobs]:打印指定队列信息和负载状态[获取指定队列中所有任务的详细信息];该命令只能指定mapred queue -list列出的队列名
    • -showacls:打印当前用户可以访问的所有队列的acl列表;该命令列出的队列可能比-list列出的多(如root用户),通过yarn queue -status <name>可以查看该命令列出的所有队列的状态
  2. mapred job <-command>:MR任务相关的命令,如list、kill、submit、status等14条命令
  3. mapred pipes <-command>:运行pipes job相关的命令

Job History

  1. 说明:整个集群中,只用在任意一个节点(默认配置无绑定)启动一个Job History服务就可以查看整个集群的作业历史,而不用在每个节点上都启动,因为它是从HDFS上读取各个节点数据的,不过一般和RM在同一个节点上
  2. 启动,两种方式:
    • mapred historyserver:一直运行,只能通过ctrl+c停止,不建议使用
    • sbin/mr-jobhistory-daemon.sh start historyserver
  3. 停止:sbin/mr-jobhistory-daemon.sh stop historyserver
  4. 常用命令:格式:mapred hsadmin <-command>:history server管理员命令,主要更新三种信息:管理员列表、超级用户组列表、用户和用户组映射关系
  5. Web UI
    • 访问地址由配置项mapreduce.jobhistory.webapp.address决定,默认0.0.0.0:19888
    • 主要功能:
      • Jobs:所有历史作业的信息,如时间、完成进度等
      • Tools:
        • UI查看本地日志
        • UI查看Job History服务状态

问题解决清单

  1. 问题描述:通过start-all.sh启动hadoop后,通过jps没有发现NodeManager进程,通过web访问m1:8042也不能正常显示
    问题解决:通过查看nodemanager启动日志发现有异常:cannot support recovery with an ephemeral server port. Check the setting of yarn.nodemanager.address。由于我并没有在yarn-site.xml中配置该项,所以通过查看官网提供的默认配置发现,yarn.nodemanager.address的默认配置是${yarn.nodemanager.hostname}:0。(网上很多资料记载的默认配置端口是8041,不知道为什么默认配置变成了0),经过配置该项为m1:8041后,再次启动,发现只有m1节点NM启动成功,其他节点依然失败,再次查看日志发现Problem binding to m1:8041,因为NM是运行在各个节点上的,所以该项配置应该对应各个节点各自的IP,所以应该配置成${yarn.nodemanager.hostname}:8041,问题解决。(需要注意修改所有节点的配置)
  2. 问题描述:按照配置文件,在core-site.xml中配置了hadoop.tmp.dir项为/mnt/m1/tmp,/mnt/m2/tmp,/mnt/m3/tmp,本意是逗号做分隔,配置三个目录,但实际上逗号并没有起到分隔的作用,而是被作为目录的一部分,只有一个目录被创建(并没有影响正常运行)
    问题解决:
    • 通过查看官网默认配置,发现该项是以file://开头的路径,所以将该项配置成file://mnt/m1/tmp,/mnt/m2/tmp,/mnt/m3/tmp后,通过start-all.sh启动,发现NM并没有被启动,通过查看日志发现,AbstractService报异常Wrong FS file://mnt/m1/tmp,/mnt/m2/tmp,/mnt/m3/tmp/yarn-nm-recovery, expected:file///(师傅说应该是因为第一个”/“被当做系统根目录处理了,所以不识别”file:/“)
    • 将该项配置成file:///mnt/m1/tmp,/mnt/m2/tmp,/mnt/m3/tmp后,通过start-all.sh启动,发现NM还是并没有被启动,通过查看日志发现,NativeDB报异常IO error:/usr/hadoop/file:/mnt/m1/tmp,/mnt/m2/tmp,/mnt/m3/tmp/yarn-nm-recovery/LOCK:No such file or direcotry,这里对比上一步可发现,NativeDB并不识别file://,而是将其当做普通路径来处理,而且由于没有根目录,所以当做相对路径处理,追加了${HADOOP_HOME}=/usr/hadoop作为根目录,但上一步报异常的AbstractService是识别”file://“的,所以AbstractService是按照多路径创建了三个目录,接着走到这里时,因为当做一个路径来open了,所以报异常。而且查看官网可发现该项配置并没有说明可以配置多个目录,所以应该是版本升级后不再支持多路径了
    • 将该项配置成正常的单路径(不再以file://的形式配多路径):/mnt/tmp,问题解决(同时注意修改其他节点的配置)

从零爬Hadoop系列_8-Hadoop2OnLinuxCluster

发表于 2016-09-26   |   分类于 Hadoop   |     |   阅读次数

Hadoop2OnLinuxCluster

本文主要是讲如何在Linux系统下安装部署Hadoop集群。

环境说明

  1. 三台Linux机器(SUSE)
  2. JDK1.8(提前下载好对应的tar.gz)
  3. Hadoop2.7.2(提前下载好对应的tar.gz)

以下所有配置需要在每个主机上都进行,但按照本文配置,可以配置一个以后复制过去,不用任何修改。另外,本文是精简配置,如果想了解更多配置参数,可参考另一篇博文或查看官网左下角的配置文件。

1. 同步时间

集群上的机器需要进行时间同步,不然运行MR任务时会报错。一般集群机器不能联网,手动修改每台机器时间。

1
2
3
4
5
6
7
1. 查看本机时间和时区:`date`
2. 设置时区:
* 执行tzselect命令查找适合于本地的时区
* 执行cp /usr/share/zoneinfo/Aisa/Shanghai /etc/localtime
3. 修改日期:date –s 15/07/2015
4. 修改时间:date –s 16:18:52
5. 将系统时间同步到硬件时间:hwclock -w

2. 关闭防火墙

如果机器上正在运行防火墙,需要把它关上。

1
停止防火墙:service iptables stop(启动防火墙:service iptables start)

但以上命令只会当次机器运行有效,机器重启又会无效,如需要,可使用如下命令:

1
2
chkconfig iptables on
chkconfig iptables off

3. 配置Host文件

首先,要先给所有机器分配好IP和hostname,hadoop会根据主机名去/etc/hosts文件中查找对应的ip。注意此处的ip和hostname,切记全文替换为自己的。

1
2
3
4
5
6
7
8
1. 查看/修改当前机器的主机名
cat/vim /etc/HOSTNAME
2. 如果修改了,通过如下命令使其立即生效
/etc/rc.d/boot.localnet start
3. 在每台机器的/etc/hosts文件末尾加上下面三行(替换相应的ip和hostname,此处假设hostname分别为m1,m2,m3):
{ip1} m1
{ip2} m2
{ip3} m3

4. 配置SSH互信

为了使集群之间无密码访问(为了以后集群通信时不用每次都输入密码),需要在机器之间配置互信(只要确保能从master无密码访问slave就好了)。配置互信前请确保已经安装并启动了ssh服务。

1
2
3
4
5
6
7
8
1. 生成密钥并配置ssh无密码登录主机(master主机)
* ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
* cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
2. 将authorized.keys文件拷贝到其他两台slave主机
* scp authorized_keys m2:~/.ssh
* scp authorized_keys m3:~/.ssh
3. 验证是否可以从master无密码登录slave主机
* ssh m2(在master主机输入)登录成功则配置成功,exit退出登录返回Master

5. 安装JDK和Hadoop

Hadoop是用java开发的,Hadoop的编译和MR的运行都需要使用JDK,所以JDK是必须安装的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1. 在安装目录下(如/usr/java)解压JDK(解压后可删除tar.gz以节省空间)
tar -zxvf java.tar.gz
2. 在安装目录下(如/usr/hadoop)解压Hadoop文件(解压后可删除tar.gz以节省空间)
tar -zxvf hadoop.tar.gz
3. 配置环境变量(vim /etc/profile末尾添加)
export JAVA_HOME=/usr/java/jdk1.8.0_19
export CALSSPATH=.:$JAVA_HOME/lib/tools.jar
export HADOOP_HOME=/usr/hadoop
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin
4. 使其立即生效
source /etc/profile
5. 验证JDK是否成功
java -version
6. 验证HADOOP是否成功
hadoop version

6. 修改Hadoop配置文件

配置文件都在${HADOOP_HOME}/etc/hadoop目录下。

6.1 配置slave文件

vim slave,写入ip或hostname。

1
2
3
m1
m2
m3

6.2 配置hadoop-env.sh

检查并确认该文件中有如下配置:export JAVA_HOME=${JAVA_HOME},但有时${JAVA_HOME}并不能生效,可选择性修改为对应的目录。

6.3 配置core-site.xml

1
2
3
4
5
6
7
8
9
10
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://m1:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/mnt/tmp</value>
</property>
</configuration>

6.4 配置hdfs-site.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<configuration>
<property>
<name>dfs.name.dir</name>
<value>/usr/local/hadoop/name</value>
</property>
<property>
<name>dfs.data.dir</name>
<value>/mnt/m1/data,/mnt/m2/data,/mnt/m3/data</value>
</property>
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
</configuration>

6.5 配置mapred-site.xml

将mapred-site.xml.template重命名为mapred-site.xml,然后修改。

1
2
3
4
5
6
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>

6.6 配置yarn-site.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<configuration>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.address</name>
<value>${yarn.nodemanager.hostname}:8041</value>
</property>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>m1</value>
</property>
</configuration>

7. 配置其他节点

至此,master节点上必要的配置完成,这时可以复制到其他两个机器上。

1
2
3
4
5
6
7
8
9
10
11
12
1. 把所有配置文件打包,便于传输
tar -zcvf /hadoop.tar.gz /usr/hadoop/etc/hadoop
2. 复制到m2、m3节点
scp /hadoop.tar.gz m2:/usr/hadoop/etc/
scp /hadoop.tar.gz m3:/usr/hadoop/etc/
3. 切换到m2主机,或直接ssh登录过去
sh m2
4. 解压打包的配置文件到/usr/hadoop/etc/目录下(自动替换原文件)
tar -zxvf /hadoop.tar.gz -C /usr/hadoop/etc/
6. 对m3做同样的操作

8. 启动验证

至此,所有配置完成,可以启动Hadoop了。

在第一次启动前,必须先格式化namenode:
hadoop namenode -format。

然后,通过${HADDDOP_HOME}/sbin/start-all.sh启动Hadoop。

之后,通过jsp在master节点上,应该可以看到以下五个进程:

1
2
3
4
5
ResourceManager
NodeManager
NameNode
SecondrayNameNode
DataNode

在slave节点上,应该可以看到以下两个进程:

1
2
NodeManager
DataNode

以上进程缺一不可,缺少的说明启动失败,可以通过查看日志查明失败原因进行修正。

正常启动以后,还可以通过Web UI查看相应的UI界面。

  1. RM的Web UI:http://${RM节点IP}:8088,即Master节点
  2. NM的Web UI:http://${NM节点IP}:50070,所有节点都有

以上列出的Web UI访问地址,是默认的配置地址,具体的配置详解、各组件的命令和UI使用,参见下一篇博文。

从零爬Hadoop系列_7-Linux突击笔记

发表于 2016-09-26   |   分类于 Linux   |     |   阅读次数

虽然在Windows上也能跑Hadoop,但总不是那个味,而且学计算机的没接触过Linux,更不是那个味,所以借此机会学一些简单的Linux基础。但并不是系统性的学习Linux,只是为了能在Linux环境下跑Hadoop,所以只看了两天,现学现用。本文主要是一些基本命令的练习和《鸟哥的Linux私房菜》中的基础知识,类似于学习笔记,好记性不如烂笔头嘛。

Linux简介

Linux简介遍地都是,想详细了解的可以深入查询了解,此处只是写一下凭自己看书留下的主要印象。

  1. 诞生:在早期电脑还只是大型机用于军事、科研等时,只能同时支撑30个左右的终端,贝尔实验室要开发一个操作系统,目标是支持300个终端,开发了四年宣告失败,实验室内部的一个员工为了方便个人档案管理,抽取失败的项目开发成Unix,慢慢在实验室内部流行开来,且有更多人来开发维护。
  2. 发展:到了90年代个人电脑流行开时,芬兰的大学生Linus通过GNU接触到Unix,把当时只能用于大型机的Unix改写移植到个人x86电脑上使用,借助GNU流行至今。
  3. 理解:操作系统从上到下依次为:用户、应用程序、内核、硬件,四者中只有内核不好理解。说得简单点,操作系统就相当于一个介于用户和硬件的中介,只有通过操作系统,用户才能使用比较统一的操作或命令来使用五花八门的硬件为我们工作,而完成这项任务的重要角色其实是内核,一个很小的东西(Windows之所以那么大是因为有那么繁杂的界面和功能)。所以在Windows下,我们和内核之间还有一个中介,而在Linux下使用命令行可以和内核直接交互,越过了层层封装,可以完成更多底层操作和功能,当然也需要相应的知识学习。
  4. 优点:Linux之所以可以流行至今,并且作为服务器的首选,主要因为以下优点:硬件要求低、开源、免费、稳定、安全、真正的多人多任务。简单点讲,就是硬件成本够低,够安全(因为开源),够稳定,反正服务器主要用来常年跑服务,不需要GUI,这不就是为服务器量身定做的吗?
  5. 缺点:命令行操作需要学习成本。虽然有GUI,但其本质还是Linux上的一个应用,不如直接操作Linux系统。

虽然当前有很多版本,但内核是一样的,所以本质上是一样的。

档案

档案相当于Linux下我们理解的文件和文件夹的统称,只由一位属性做区分。

档案属性

档案属性共十位,如drwxrwxrwx,若下标记为0-9,则:

  1. 0位:档案类型
    • d:目录
    • -:常规档案
    • l:连结档,link file
    • b:区块(block)设备档,装置文件里面的可供存储的接口设备;
    • c:字符(character)设备档,装置文件里面的串行端口设备,例如键盘、鼠标;
  2. 123位:拥有人的权限
    • r:可读,数值4
    • w:可写,数值2
    • x:可执行,数值1(同win下的.exe等扩展名的标示作用,在Linux下是否可执行仅靠该标注。另外当0位为d时,表示是否可以在此目录下执行命令)
  3. 456位:与拥有人同群组的权限:同上
  4. 789位:非同群组的权限:同上
  5. 注意点:当文档类型为d即目录时,要特别注意权限x,例如drwxr–r–,此时除了拥有者外,其他人均不能查看该目录,为什么呢?虽然有r权限,但没有x权限,即不能在该目录下执行任何命令,如ls,也就无法查看,相当于没有进入该目录。

连结档link file

  1. inode table:inode中存储着档案的属性,及该档案放置在哪一个block中等信息
  2. block area:真正存储数据的地方,所以访问档案时,先查inode table,再到对应的block操作数据
  3. 对于【目录】文件本身,只有对应的inode,没有对应的block
  4. Hard Links:新建立一个inode指向档案的block区块,即它允许一个档案有多个不同的路径名,可以防止误删(因为删除操作只是删除对应的inode,类似于JVM的GC)
    • 缺点1:不能跨filesystem,因为不同的filesystem有不同的inode table
    • 缺点2:不能link目录
  5. Symbolic Links:新建立一个特殊的档案文件,通过保存真正的档案位置从而把操作导向真正的档案,类似于Windows的快捷方式,如果源文档被删除,该link会打不开
  6. ln [-s] [src] [des]:创建连结档,s:symbolic,即默认为hard link
  7. ll和连结档

    • ll共7列,分别是:属性、link个数、拥有者、群组、修改时间、文件名;
    • 假设当前目录下有一个test.txt档案,在分别建立其一个硬链接hard.txt和软连接soft.txt之后,ll命令结果如下:

      1
      2
      3
      4
      total 8
      -rw-r--r-- 2 root root 77 Jul 1 15:15 hard.txt
      lrwxrwxrwx 2 root root 8 Jul 1 15:21 soft.txt -> test.txt
      -rw-r--r-- 2 root root 77 Jul 1 15:15 test.txt
    • 可以发现有一下几个注意点:

      1. 硬链接的属性首位并非l,而是普通的-,软连接才是l
      2. 源文件和硬链接的link数都为2,而且此时两文件出了命名不同外,其他全部一模一样,已经不分“真假”了,都是真的
      3. 软连接和源文件还是能分辨出“真假”的,软连接的link数为1,而且软连接的命名有指向源文件的说明
      4. 软连接的访问权限全开了

常见目录的大致内容

  1. /bin:存放一般用户常用的执行档,如ls,rm,mkdir,rmdir等
  2. /boot:存放Linux核心,以及和开机相关的档案,重要!
  3. /dev:即device,Linux将设备视为档案,如硬盘、软盘、光驱等
  4. /etc:存放系统在开机过程中需要读取的档案,重要!
  5. /home:系统使用者的家目录
  6. /lib:存放Linux执行或编译一些程序时使用到的一些库
  7. /list+found:系统不正常产生错误时,会将一些遗失的片段存在此目录下,通常会自动出现在dev目录下,如加装一个硬盘于/disk中,则会产生/disk/lost+found目录
  8. /mnt:软盘和光盘预设挂载点,通常软盘挂在/mnt/floppy下,光盘挂在/mnt/cdrom下,不过不是定死的
  9. /proc:系统核心及执行程序的一些信息。该目录在系统启动时自动被挂上,且不占用硬盘空间,因为里面都是内存内的数据
  10. /root:系统管理员的家目录
  11. /sbin:存放系统管理员常用的执行档,如:fdisk等
  12. /tmp:暂时存放档案的地方,要定期清理,不存重要数据
  13. /usr:存放相当多的系统信息,内有许多目录,存放程序和指令等等,类似windows下的program files,重要!
  14. /var:重要!所有服务的登录文件或log files都在/var/log目录下,数据库如MySQL的数据库则在/var/lib目录下,其他目录如邮件等也在这里

常用命令

档案

  1. df -h:
    • df:Disk Filesystem
    • h:Human readable
  2. du -sh:
    • du:Disk Usage
    • s:Summarize
    • h:Human readable
  3. ll:ls -l的别名
    • ls:List directory contents
    • l:Long Listing format
  4. ls [dir]:list,列出指定目录下所有文件(默认当前路径)
  5. mv:move
  6. cp:copy
  7. scp:secure copy(remote file copy program)
  8. rm:remove
  9. find -name
  10. ls [-l]:
  11. cd [dir]:Change Directory,切换到指定路径
    • 目录符号
      • .:当前目录;
      • ..:上级目录;
      • ~:当前用户的家目录;
      • ~user:user这个用户的家目录
  12. pwd:Print Working Directory,显示当前目录
  13. mkdir [-m(权限)/p(递归全建)] [name]:新建一个目录
  14. rmdir [-p(递归全删)] [name]:删除一个空目录
  15. 查看档案内容
    • cat:concat,打印档案的全部内容
    • tac:从最后一行往前显示,和cat相反
    • more:分页显示
    • less:分页显示,可以往前翻页
    • head:头10行
    • tail:最后10行
    • tailf:同tail --follow=[name],常用于跟踪日志文件
  16. vi:使用vim编辑
  17. grep [text]:Globally search a Regular Expression and Print,文本搜索
  18. find [filename]:相当于Windows下文件管理器的搜索

进程

  1. ps -ef | grep <pid>:
    • ps:Processes Snapshot
    • e:同A,All
    • f:Full-Format list
    • grep:Globally search a Regular Expression and Print
  2. top -p <pid>:
    • top:display Linux Tasks
    • p:Process
  3. kill <pid>

网络

  1. lsof -i:<port>:
    • lsof:List Open File
    • i:Internet,最多100个参数
  2. ifconfig:network Interface configure
  3. netstat -anp | grep :
    • netstat:network statistics
    • a:All,both listening and non-listening sockets
    • n:Numerical addresses
    • p:show the PID and name of the Program to which each socket belongs
  4. ethtool :网卡工具,查看或设置网卡参数。可以配合ifconfig使用。
  5. ping

从零爬Hadoop系列_6-Hadoop2OnWindows

发表于 2016-07-31   |   分类于 Hadoop   |     |   阅读次数

Hadoop2OnWindows

本文主要是讲如何在Windows系统下编译、安装部署单机模式的Hadoop。

下载Hadoop源码

当前比较流行的Hadoop源代码版本有两个:Apache Hadoop和Cloudera Distributed
Hadoop(简称 CDH) 。Apache Hadoop是由雅虎、Cloudera、Facebook等公司组成的Hadoop社区共同研发的, 它属于最原始的开源版本,在该版本基础上,很多公司进行了封装和优化,
推出了自己的开源版本,其中,最有名的一个是Cloudera公司发布的CDH版本。

YARN属于Hadoop 2.0的一个分支,此处我使用的是Apache版本的2.7.2。

环境说明

为什么把环境说明放在第二步呢?因为所需环境在源码文件里有明确说明。把刚才下载的源码解压到合适的路径下,然后在源码根目录下有一个BUILDING.txt文件,该文件依次列出了Unix和Windows的所需环境。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
----------------------------------------------------------------------------------
Building on Windows
----------------------------------------------------------------------------------
Requirements:
* Windows System
* JDK 1.7+
* Maven 3.0 or later
* Findbugs 1.3.9 (if running findbugs)
* ProtocolBuffer 2.5.0
* CMake 2.6 or newer
* Windows SDK 7.1 or Visual Studio 2010 Professional
* Windows SDK 8.1 (if building CPU rate control for the container executor)
* zlib headers (if building native code bindings for zlib)
* Internet connection for first build (to fetch all Maven and Hadoop dependencies)
* Unix command-line tools from GnuWin32: sh, mkdir, rm, cp, tar, gzip. These
tools must be present on your PATH.

按照上边的说明(如果你下的版本和我不一样,就看你的BUILDING文件),依次下载配置好环境变量,其中Protocol只是一个exe编译器,把路径配到PATH中即可,其他环境的安装配置不再详述(对于if的可选项,我都没配,按需选配)。

Windows SDK安装错误

如果你和我一样,在安装Windows SDK 7.1时出现如下图的错误:
Windows_SDK_install_error
具体错误原因我也没查到,我的解决方法是:

  1. 卸载当前系统中非4.0的.Net
  2. 下载安装.Net 4.0
  3. 重启电脑,再次安装Windows SDK

如果不灵,那我也没办法了-_-!

使用Maven编译

之所以不直接在IDEA中导入,是因为如果直接把源码导入为Maven项目,在下载好对应的依赖包后,你依然会发现部分类或函数无法找到。这是因为自Hadoop 2.0开始使用了Protocol Buffers定义了RPC协议,而这些Protocol Buffers文件直到在Maven编译源码时才会生成对应的Java类,因此如果源码中引用了这些类,自然就无法找到了。所以倒不如先用Maven编译好了再导入来得省事。

编译步骤

  1. 找到刚才安装好的Windows SDK,打开Windows SDK command prompt
  2. 进入刚才下载好解压过的Hadoop源码根目录
  3. 如果是32位系统,执行命令:set Platform=Win32(注意大小写)
  4. 如果是64位系统,执行命令:set Platform=x64(注意大小写)
  5. 然后执行命令:mvn package -Pdist,native-win -DskipTests -Dtar

mvn_package
然后就等着编译和下载需要的依赖包吧(-DskipTests是为了省去对Test的编译)。

编译错误

  1. 如果编译失败,首先检查上边说的环境是否都配好了,都已经写进PATH环境变量;其次检查命令参数,注意不要想当然的把Win32写成x32,或者把x64写成Win64,set Platform要一字不差,大小写也不能错
  2. 如果在编译期间出现如下图的错误,这是因为没有准备Protocol Buffers环境,下载加进PATH即可解决(记得重新打开Windows SDK command prompt命令行,不然不会使用新的PATH变量)。
    protoc_error
  3. 还有一种错误,当时没有截图,记得是在编译hadoop-common包时出现的,具体错误信息不记得了,原因是因为CMake版本太低,重新下载最新版本配好环境即可解决

免编译走捷径

如果你在以上步骤中步履维艰,出错不断,你也可以参考这个网址中的“Step 3”步骤中的说明。其做法是下载他已经编译好的,Windows系统下需要的文件,然后直接替换掉官网上的Unix发布版中的bin文件即可。所以捷径只需两步:

  1. 下载官网上的binary文件
  2. 下载上述网址中的文件,并替换掉官网文件中的bin文件

源码学习环境

等编译好后,就可以直接导入IDE了,我这里使用的是IDEA,直接导入即可,如果你使用的是Eclipse,还需要在编译完成后执行命令mvn eclipse:eclipse -DskipTests将其转为Eclipse项目。

其中我在系列开篇时提到的Hadoop四大模块对应的项目依次如下:

  1. hadoop-common-project:Hadoop 基础库所在目录,该目录中包含了其他所有模块可能会用到的基础库,包括RPC、Metrics、Counter等
  2. hadoop-mapreduce-project:MapReduce框架的实现,在MRv1中,MapReduce 由编程模型(map/reduce)、调度系统(JobTracker 和 TaskTracker)和数据处理引擎(MapTask和ReduceTask)等模块组成,而此处的MapReduce则不同于MRv1中的实现,它的资源调度功能由新增的YARN完成(编程模型和数据处理引擎不变),自身仅包含非常简单的任务分配功能
  3. hadoop-hdfs-project:Hadoop分布式文件系统实现,不同于Hadoop 1.0中单NameNode实现,Hadoop 2.0支持多NameNode,同时解决了NameNode单点故障问题
  4. hadoop-yarn-project:Hadoop资源管理系统YARN实现。这是Hadoop 2.0 新引入的分支,该系统能够统一管理系统中的资源,并按照一定的策略分配给各个应用程序

这时我们就可以结合之前看书的理解,对着代码再梳理一下,加深理解。

Hadoop安装部署

如果刚才编译成功的话,我们可以在Hadoop源码根目录下的target文件中得到一个二进制的hadoop-2.7.2.tar.gz(机智如你可能会问,干嘛费这么大劲,直接去官网下载不得了?因为官网的是Unix的发行版,不能在Windows上直接部署安装)。

解压这个二进制文件,我们将得到如下目录:

  1. bin:Hadoop最基本的管理脚本和使用脚本所在目录,这些脚本是sbin目录下管理脚本的基础实现,用户可以直接使用这些脚本管理和使用Hadoop
  2. etc:Hadoop配置文件所在的目录,包括 core-site.xml、hdfs-site.xml、mapred-site.xml等从Hadoop 1.0继承而来的配置文件和yarn-site.xml等Hadoop 2.0 新增的配置文件
  3. include:对外提供的编程库头文件(具体动态库和静态库在lib 目录中),这些头文件均是用C++定义的,通常用于C++语言访问HDFS或者编写MapReduce程序
  4. lib:该目录包含了Hadoop对外提供的编程动态库和静态库,与include 目录中的头文件结合使用
  5. libexec:各个服务对应的Shell 配置文件所在目录,可用于配置日志输出目录、启动参数(比如 JVM 参数)等基本信息
  6. sbin:Hadoop管理脚本所在目录,主要包含HDFS和YARN中各类服务的启动/ 关闭脚本
  7. share:Hadoop各个模块编译后的JAR包所在目录

对于我们呢,只会用到etc里边的配置文件和sbin里边的管理脚本。下边我们开始进行主题——Hadoop2OnWindows,单节点(伪分布式)集群安装部署。

1. 配置文件

这里所提的配置文件都在/etc/hadoop目录下。

slaves

1
localhost

hadoop-env.cmd

注意把HADOOP_PREFIX的值换成自己的解压路径。

1
2
3
4
set HADOOP_PREFIX=D:\Project\hadoop-2.7.2-src
set HADOOP_CONF_DIR=%HADOOP_PREFIX%\etc\hadoop
set YARN_CONF_DIR=%HADOOP_CONF_DIR%
set PATH=%PATH%;%HADOOP_PREFIX%\bin

core-site.xml

1
2
3
4
5
6
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://0.0.0.0:19000</value>
</property>
</configuration>

hdfs-site.xml

1
2
3
4
5
6
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
</configuration>

mapred-site.xml

先将文件mapred-site.xml.template重命名然后编辑。

1
2
3
4
5
6
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>

yarn-site.xml

1
2
3
4
5
6
7
8
9
10
11
<configuration>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
</configuration>

2. 环境变量

执行脚本命令文件%HADOOP_PREFIX%\etc\hadoop\hadoop-env.cmd,使所需的环境变量生效。

3. 格式化HDFS文件系统

对于第一次启动,首先要格式化HDFS的namenode,通过执行如下命令:
%HADOOP_PREFIX%\bin\hdfs namenode -format

4. 启动Hadoop

这里有两种方法:

  1. 第一种,依次执行如下两个脚本命令文件:%HADOOP_PREFIX%\sbin\start-dfs.cmd、%HADOOP_PREFIX%\sbin\start-yarn.cmd
  2. 第二种,执行这个脚本命令文件:%HADOOP_PREFIX%\sbin\start-all.cmd

其实两种方法本质是一样的,后者只不过是顺序调用前者。

5. 验证

启动以后,执行jps命令,如果看到如下4个进程,说明启动成功,否则查看启动日志查明原因。

1
2
3
4
ResourceManager
NodeManager
NameNode
DataNode

参考

在Windows系统下编译安装Hadoop简直是一种折磨,步履维艰,这个过程中遇到各种错误,本文只是列出了我记载的几个,大致步骤主要是参考这个链接:Hadoop2OnWindows

从零爬Hadoop系列_4-《Hadoop技术内幕2》NodeManager

发表于 2016-07-24   |   分类于 Hadoop   |     |   阅读次数

NM剖析

NM是YARN中单个节点上的代理,负责管理Hadoop集群中单个计算节点。和RM剖析一样,我们可以先从最开始的YARN的工作流程中观察,NM都需要和哪些组件进行交互,分别需要完成什么功能,则在NM内部,便会细分出来各个功能类别的模块,在每个模块内部,还可以继续按照功能细分,落实到各个组成的类或接口。

NM基本职能

  1. NM作为RPC的client端,周期性的主动向RM发起请求,这些请求包括向RM注册、汇报节点健康状况和节点上所有Container运行状态;并以请求应答的形式,领取RM下达的命令
  2. NM作为RPC的server端,接收并处理AM下达的命令,这些命令包括启动Container、杀死Container、获取Container执行状态等,并返回执行结果
  3. 个人理解:其实以上两点都是NM作为整体对外负责的功能,而且并不是它最主要的功能,不要忘了,所有计算任务都是以Container的形式运行在NM上,所以NM最主要的功能是内部Container的管理,比如:
    • 既然要运行任务,就需要下载任务运行所需的资源,每个NM上有很多Container,需要考虑并行下载和文件管理问题
    • 资源下载完以后,还要监控各个Container的运行状态,进行日志记录
    • Container运行完成以后,还要进行之前下载资源的清理

NM内部架构

通过对YARN工作流程和NM职能的分析,可以猜测NM至少包含一下模块:

  1. AM管理模块:每个NM上可以运行多个AM,需要有对应的管理模块负责信息归总和管理
  2. Container管理模块:每个NM上可以运行多个Container,且可以属于不同的AM,需要有对应的管理模块负责信息归总和管理

同时和RM一样,NM内部各个组件也是基于事件驱动的,NM内部架构组成如下:

  1. NodeStatusUpdater:是NM和RM通信的唯一通道,对应职能1
  2. ContainerManager:是NM中最核心组件之一,有一下组件:
    • RPC Servier:是AM和NM通信的唯一通道,对应职能2
    • ResourceLocalizationService:负责Container运行所需资源的本地化,即从HDFS上下载,同时尽量分摊到各个磁盘上,避免访问热点,同时添加访问权限
    • ContainersLauncher:维护了一个线程池并行完成Container相关的操作,比如启动或杀死Container,其中启动的命令来自AM,杀死的命令来自AM或RM(资源抢占时)
    • AuxServices:NM允许用户以附属服务的方式扩展自己的功能
    • ContainerMonitor:负责监控Container的资源使用量,防止超过RM分配的量,在YARN中,只有内存是通过它监控的
    • LogHandler:可插拔式组件,用户通过它控制Container日志保存方式:写到本地磁盘或上传到一个文件系统中
    • ContainerEventDispatcher:Container事件调度器,负责将ContainerEvent类型的事件调度给对应的Container的状态机ContainerImpl
    • ApplicationEventDispatcher:Application事件调度器,负责将ApplicationEvent类型的事件调度给对应的Application的状态机ApplicationImpl
  3. NodeHealthCheckerService:周期性运行自定义脚本和向磁盘写文件,以检查节点健康状况,然后通过NodeStatusUpdater汇报给RM,若发现不健康RM会将其加入黑名单,不再分配,直到其转为健康状态
  4. DeletionService:负责删除Container运行完成后遗留的无用的资源文件或临时输出文件,为了避免同步删除文件带来的开销,NM将删除文件功能服务化,进行异步删除
  5. Security:安全模块,主要两部分:
    • ApplicationACLsManager:确保访问NM的用户的合法性,比如Web UI访问,该组件为每个应用程序维护了一个ACL列表
    • ContainerTokenSecretManager:检查收到的各种访问请求的合法性,确保这些请求操作已被RM授权
  6. WebServer:通过Web界面展示该节点上所有应用程序运行状态、健康状况、日志等信息
    NM内部架构图

健康节点状况监测

  1. 自定义Shell脚本:
    • NodeHealthScriptRunner服务周期性的执行监测脚本并检查其输出,如果标准输出打印出以字符串“ERROR”开头的语句,则认为节点不健康,通过心跳告诉RM
    • 自定义脚本的好处:
      • 可作为节点负载的反馈:因为当前YARN只对CPU和内存资源进行分配和隔离,所以用户可以通过自定义脚本检查网络、磁盘、文件系统等运行状况缓解这个问题
      • 认为暂时维护NM:可以通过脚本输出ERROR停止NM接受新任务比便进行维护
  2. 检测磁盘损坏数目:
    • 另外一种健康检测机制,默认开启,即与脚本检测同时进行,双重检查
    • 检测方法:如果一个目录具有rwx权限,则认为它是正常的,否则加入坏磁盘列表,当比例过低时,便认为NM不健康,通过心跳告诉RM

分布式缓存机制

  1. 主要作用:将用户应用程序执行时需要的外部文件资源自动透明地下载并缓存到各个节点上,省去用户手动部署。同时NM并不是一下子把所有资源下载下来,而是根据启动的Container按需下载,而且采用一定的缓存置换算法定期清理失效文件(默认10分钟)
  2. 工作流程:
    • 步骤1:客户端将应用程序所需的文件资源提交到HDFS上
    • 步骤2:客户端将应用程序提交到RM上
    • 步骤3:RM与某个NM通信,让NM启动对应的AM,NM收到命令后,首先从HDFS下载文件(缓存),然后再启动AM
    • 步骤4:AM与RM通信,以请求和获取Container
    • 步骤5:AM收到新分配的Container后,与对应的NM通信,启动任务
    • 步骤6:如果该应用程序第一次在该节点上启动任务,NM首先从HDFS上下载文件缓存到本地,然后启动任务
    • 步骤7:NM后续收到启动任务请求后,如果有缓存,则直接启动,否则先等缓存成功再启动
  3. 资源可见性(三种):
    • PUBLIC:节点上所有用户共享,即只要存在,其他用户不用再下载
    • PRIVATE:节点上同一用户的所有应用程序共享
    • APPLICATION:节点上同一应用程序的所有Container共享
  4. 资源分类(三类):
    • ARCHIVE:归档文件,当前支持.jar、.zip、.tar.gz、.tgz、和.tar5种,NM可以自动解压缩
    • FILE:普通文件,NM只下载,没有额外处理
    • PATTERN:以上两种类型的混合体,用户需要通过正则表达式指定哪些属于ARCHIVE需要自动解压
  5. YARN分布式缓存的实现
    • 三种可见性资源分别放置在不同的目录下,通过目录权限实现不同的可见性
    • PUBLIC资源下载:由公共服务ResourceLocalizationService中的一个公用线程PublicLocalizer下载,它内部维护了个线程池并行下载
    • PRIVATE和APPLICATION:由公共服务ResourceLocalizationService中的一个专门线程下载:一个Container对应一个LocalizerRunner线程

目录结构管理

  1. 由于同一个NM上不同的Container往往并行向本地磁盘写数据,为了避免占用大量IO资源造成相互干扰,尽量提高写数据的可靠性和并发写性能,YARN允许NM配置多个挂在不同磁盘的目录作为中间结果存放目录,对于任意一个应用程序,YARN会在每个磁盘中创建相同的目录结构,然后采用轮询策略使用这些目录
    NM目录结构
  2. 目录分类:
    • 数据目录:存放Container运行所需和中间数据
    • 日志目录:运行时输出的日志
  3. 日志清理机制:
    • 定期删除(默认):默认3小时,超时删除
    • 日志聚集转存:把日志上传到HDFS上,上传后删除,可以指定三种可以转存的类型(顾名思义):
      • ALL_CONTAINER
      • APPLICATION_MASTER_ONLY
      • AM_AND_FAILED_CONTAINER_ONLY

状态机管理

  1. 三类状态机:
    • Application状态机:维护的信息是RM端维护的子集,方便对一个节点上同一个应用程序的所有Container进行统一管理
    • Container状态机:维护一个Container的生命周期,三个阶段:
      • 资源本地化
      • Container启动
      • 资源清理(资源本地化逆过程,这里的资源指临时文件,而非硬件资源):
        • 这一步的清理,只是Container的临时数据,如Tokens文件和Shell运行脚本等
        • 因为各个Container之间可能有依赖关系,所以NM规定只有在一个应用程序的所有Container全部结束以后,由RM发送广播,NM才能清理程序所占的所有资源和中间数据
      • 可以翻书了解详细的过程,进一步理解基于事件驱动的应用
    • LocalizedResource状态机:维护一种资源的生命周期,从初始化、到下载中、到下载完成/下载失败
  2. 个人理解:三类状态机的关系:从大流程上来看,基本可以认为是以下关系:
    • NM启动一个AM,创建对应的Application状态机
    • Application状态机在收到AM发送的启动Container请求后,会创建对应的Container状态机(一个或多个)
    • Container运行之前,需要先下载缺少的资源,即会创建对应的LocalizedResource状态机(一个或多个)进行资源下载,并等待所有资源下载完,然后进入运行状态

资源隔离

  1. 内存资源隔离:基于线程监控:
    • 由服务ContainersMonitorImpl实现,它保存了每个Container进程pid,内部的MonitoringThread每隔一段时间(默认3000ms)扫描所有正在运行的Container进程树
    • 步骤:
      • 读取/proc//stat文件构造进程树
      • 判断单个任务内存使用量是否超过最大值内存量
    • 由于JVM创建一个子进程时,采用了“fork()+exec()”模型,意味着进程创建之后、执行之前会复制一份父进程内存空间,进而使得进程数在某一小段时间内存使用量翻倍,为了防止误杀,Hadoop赋予每个进程“年龄”属性,并规定刚启动的进程年龄为1,MonitoringThread线程每更新一次,各个进程年龄加1,则内存超量使用而被杀死的判断标准为:
      • 如果一个Container对应的进程树中所有进程(年龄大于0)总内存超过用户设定最大值的两倍
      • 或者所有年龄大于1的进程总内存量超过用户设定的最大值
      • 只要满足其一,则向对应的Container发送ContainerEventType.CKILL_CONTAINER事件将其杀死
    • 个人理解:内存隔离并不是真正的物理上的隔离,其他内存还是可见的,只是简单的一个线程监控使用量而已,所以需要用户在设定内存最大值时有良好的预估和分配
  2. CPU资源隔离:使用Cgroups(Control groups)
    • Cgroups是Linux内核提供的一种可以限制、记录、隔离进程组所使用的物理资源的机制,YARN通过使用其子系统CPU实现CPU资源隔离,该子系统使用调度程序控制任务对CPU的访问
    • Cgroups相比于虚拟机,是一种轻量级资源隔离方案
    • Cgroups只能保证应用程序的CPU使用下限,但不能限制上限。举例说明,某个节点上有10个虚拟CPU:
      • 若该节点上只有一个应用程序A,且设定的CPU需求为4,则A最多能够使用全部CPU
      • 若该节点上有两个应用程序A和B,且CPU需求都为4,则A和B都最多能够使用全部CPU,最少使用一半
      • 若该节点上有三个应用程序A、B、C,CPU需求依次为4、4、2,则它们最多均可以使用全部CPU,最少可使用CPU资源比例依次为:4/(4+4+2)10=40%、4/(4+4+2)10=40%、2/(4+4+2)*10=20%
    • NM默认没有启用任何CPU资源隔离机制
    • 个人理解:CPU隔离也不是真正的物理上的隔离,而且按照上边的说明,基本可以说没有隔离,只能保证下限而已,同样需要用户对资源的使用量有良好的分配和设定
  3. 所以总的来讲,所谓的资源隔离是比较虚的,不能顾名思义

小结

  1. 对NM的理解:作为资源管理系统YARN的一个重要服务,NM管理的是Container,而不是任务,一个Container中可能运行着各种任务,但是对NM而言是透明的,它只负责Container相关的操作,比如管理Container的生命周期等。这也是YARN能够作为一个通用的资源管理平台的重要原因,它不管具体的任务类型或内容,只要按它规定的规范进行封装就可以提交运行
  2. 对Container的理解:Container从头到尾都只是一个逻辑抽象概念,RM把资源抽象为Container发送给AM,AM再发给NM,NM则会在Container描述的运行环境中启动任务,其实就是启动一个进程,然后在该进程下跑任务和各个状态机

思考问题

  1. 第一天的疑问1:怎么保证AM没有撒谎?比如AM并没有向RM申请资源,绕过RM直接通知NM启动任务?
    • 就是由Secret模块下的ContainerTokenSecretManager通过Token检查保证的
  2. 第一天疑问2:YARN的工作流程第6步,为什么运行脚本而不是直接运行命令?
    • 因为直接执行命令可能让一些特殊符号发生转义
  3. 第二天的疑问3:Container只是对资源逻辑上的划分和规定,在实际使用中,如何保证严格的物理划分或隔离?
    • 没有严格的物理划分或隔离,对于内存是监控上限,对于CPU是保证下限
  4. 本章只介绍了节点的健康检测,那NM向RM心跳时汇报的所有Container的运行状态都包括哪些呢?又是怎么汇总的?
  5. 根据YARN工作流程的第七步的描述,听起来应该是各个Container心跳式的主动向AM汇报运行状态,但按照基本职能2的描述,只有一个AM主动查询运行状态的接口,那主动汇报的接口呢?本章好像没有提。

从零爬Hadoop系列_3-《Hadoop技术内幕2》RM-资源调度器

发表于 2016-07-24   |   分类于 Hadoop   |     |   阅读次数

资源调度器

资源调度器对应昨天总结的RM中的资源调度模块,它是RM中一个插拔式的服务组件,对于资源调度器的理解,可以从两个角度出发:

  1. 资源:从资源角度出发,资源调度器负责管理NM向RM反馈的资源情况,并根据一定策略合理的进行资源分配
  2. 任务:从任务即应用程序出发,资源调度器负责从任务队列中,根据一定策略挑选出合适的任务分配给它资源,让它运行

MRv1中的资源调度器

单队列FIFO调度机制,适用于批处理场景,面对的发展背景:随着Hadoop的普及,单个Hadoop集群上的用户量和应用程序种类不断增加。

  1. FIFO的缺点:
    • 不同应用程序对硬件资源需求侧重不同,FIFO不能充分利用集群资源
    • 不同用户对应用程序的服务质量要求(QoS:Quality of Service)不同,FIFO不能满足多样化的需求:
      • 批处理作业:耗时长,对反应时间没有严格要求,如数据挖掘、机器学习
      • 交互式作业:要求及时性,如SQL查询(Hive)
      • 生产性作业:要求有一定量的资源保证,如统计值计算、垃圾数据分析等
  2. 新的需求:适用于多用户的资源调度器,能够根据不同用户需求或不用应用程序的QoS针对性地进行资源分配和调度,充分利用集群资源
  3. 多用户资源调度器设计思路:
    • 在一个物理集群上虚拟多个Hadoop集群,每个集群各自拥有全套独立的Hadoop服务,每个虚拟集群满足不同的需求,典型的代表是HOD:Hadoop On Demand
    • 扩展YARN调度器,使之支持多个队列多用户,典型代表:
      • Yahoo!的Capacity Scheduler
      • Facebook的Fair Scheduler
  4. HOD:主要依赖于一个资源管理器(Torque)为它分配、回收节点和管理各个节点上的作业运行情况,HOD只需在资源管理器分配的节点上运行Hadoop守护进程和MR作业即可,HOD只在Hadoop 1.0中提供,Hadoop 2.0不再提供,这里也不再详述,主要缺陷如下:
    • 多个虚拟集群不方便管理
    • 多个独立的虚拟集群不能共享资源,利用率低下
    • 虚拟集群通常使用一个外部全局共享的HDFS,即丧失了数据本地特性

YARN资源调度器

基本架构

  1. YARN自带三种常用资源调度器,而且是插拔式的,用户可以按照接口规范自定义实现自己的:
    • FIFO
    • Capacity Scheduler
    • Fair Scheduler
  2. YARN的资源调度器本质上是一个事件处理器,共需要处理来自外部的6种事件类型,并做不同的相应处理,其中NODE_UPDATE是最重要的事件,它会触发资源调度器最核心的资源分配机制;如下图:
    资源调度器事件处理

  3. 资源表示模型:

    • 抽象为Container,目前仅支持虚拟CPU和物理内存
    • 其中CPU参数是虚拟的,比如机器A有16个CPU,机器B有8个CPU,而且每个CPU的性能都是机器A的一倍,则两者CPU的配置参数可以都是16或100等
    • 两者参数都有取整参数配置,比如CPU默认取整单位为1,即CPU需求3.5,即取为4
  4. 资源调度模型:
    • 双层资源调度模型:
      • 第一层:RM中的Scheduler将资源分配给各个AM,资源调度器主要关注这一层;
      • 第二层:AM进一步将资源分配给它内部的各个任务,该层完全由用户应用程序决定;
    • 资源分配过程:
      • 分配过程是异步的,分为两个阶段:
        1. AM周期性地心跳,请求资源并获取已经分配到的资源(不是当次请求的,而是之前的);
        2. NM向RM汇报各个Container运行状态,如果RM发现有空闲的,则进行一次资源分配,并将分配的资源保存到对应的应用程序数据结构中,等待下次AM发送心跳信息时取走(即阶段1);
      • 详细步骤:
        1. 步骤1:NM通过周期性心跳汇报节点信息
        2. 步骤2:RM为NM返回一个心跳应答,包括需要释放的Container列表等信息
        3. 步骤3:RM收到来自NM的信息后,会触发一个NODE_UPDATE事件
        4. 步骤4:RecourceScheduler收到NODE_UPDATE事件后,会按照一定的策略将该节点上的空闲资源(步骤2中有释放的资源)分配各应用程序,并将分配结果放到一个内存数据结构中,等待AM下次心跳时领取
        5. 步骤5:AM向RM发送周期性的心跳,汇报资源需求,并领取已经分配到的Container
        6. 步骤6:RM收到来自AM心跳信息后,把新的资源需求更新到对应的数据结构中,并返回为它分配的Container
        7. 步骤7:AM收到新分配的Container列表后,会将这些Container进一步分配给它内部的各个任务
    • 资源保证机制:
      • 增量资源分配(YARN采用的):缺点是预留资源会导致资源浪费,利用率降低
      • 一次性资源分配:缺点是会产生饿死现象
    • 资源分配算法:
      • 主资源公平调度算法(Dominant Resource Fairness,DRF),适用于多资源和复杂需求的环境,主要思想是把多维度资源调度问题转化为单资源调度问题,比例大的资源即为主资源,然后把资源分配给主资源所需份额最小的
      • 最大最小公平算法(max-min fairness):优点是小作业可以快速获取资源并完成
    • 资源抢占模型:
      • 资源抢占:在资源调度器中,每个队列可设置一个最小资源量和最大资源量,作用顾名思义,但最小资源量并不是绝对的底线,当某个队列不需要任何资源时,会将空闲资源暂时借给其他需要的队列使用,所谓的抢占就是:当某个把资源借出去的队列突然收到提交的应用程序急需资源时,就需要把借出去的资源抢占回来,采用的策略是先等待再强制抢占
      • 大致步骤:
        1. 步骤1:SchedulingEditPolicy探测到需要抢占的资源,将需要抢占的资源通过事件DROP_RESERVATION和PREEMPT_CONTAINER发送给RM
        2. 步骤2:RM调用ResourceScheduler的dropContainerReservation和preemptContainer函数,标注待抢占的Container
        3. 步骤3:RM收到来自AM的心跳,并通过应答的形式把待释放的资源总量和待抢占的Container列表返回给它,AM收到列表后,可以选择如下操作:
          • 杀死这些Container
          • 选择并杀死其他Container凑够数量
          • 不做任何处理,过段时间可能有Container自行释放或被RM杀死
        4. 步骤3:SchedulingEditPolicy探测到一段时间内,AM为自行杀死约定的Container,则将这些Container封装到KILL_CONTAINER事件中发送给RM
        5. 步骤5:RM收到后调用ResourceScheduler的killContainer函数,标注这些待杀死的Container
        6. 步骤6:RM收到来自NM的心跳,并以应答的形式把待杀死的Container列表返回给它,NM收到后,将这些Container杀死,并通过心跳告知RM
        7. 步骤7:RM收到来自AM的心跳,并通过应答的形式把已经杀死的Container列表发送给它(可能AM早已通过内部通信机制知道了)
      • 需要考虑的问题:
        • 资源抢占,并不是简单的把借出去的原原本本的抢回来,而是通过一定的计算,来决定抢占哪些队列的资源(大致是抢占这种队列:资源使用量超过了参数设定的本应使用的量)
        • 如何使资源抢占代价最小:
          • YARN优先选择优先级低的Container
          • 并没有直接杀死,而是先告知AM自行处理,此时AM可以做一些进度保存等

层级队列管理机制:

YARN以树状层次的结构组织多个队列,其中用户只能把应用程序提交到最底层的叶子队列,非叶子队列的属性即下边所有叶子队列的属性和。
层级队列

  1. 特点:
    • 子队列;
    • 最小容量:
      • 每个子队列都有一个最少容量比,表示可以使用父队列的容量的百分比
      • 调度器总是优先把资源分配给资源使用率最低的队列,比如队列Q1和Q2的最小容量分别是10和20,当前两个队列以使用的资源都是5,则优先分配给Q2
      • 如上所述,不是绝对的底线,可以借出使用
    • 最大容量
  2. 队列管理机制:
    • 用户权限管理:基础OS用户管理之上,增加了“队列”这一用户组织单元,同一用户或用户组可以对应一个或多个队列
    • 系统资源管理:管理员设置每个队列的资源容量信息,调度器按照约束进行调度
  3. 命名规则:ROOT.A.A1,避免重名

Capacity Scheduler和Fair Scheduler

  1. Capacity Scheduler特点:
    • 容量保证:可以设定上下限,同一队列的应用程序共享队列资源
    • 灵活性:空闲资源可以外借出去和抢占回来,利用率高
    • 多重租赁:管理员可以按用户或按应用程序类别分不同的队列,并给不同队列设定多重约束,支持多用户共享集群和多应用程序同时运行
    • 安全保证:
      • 每个队列有严格的ACL列表控制访问用户
      • 每个用户可指定哪些用户可以查看或控制自己的应用程序
      • 管理员可指定队列管理员或集群管理员
    • 动态更新配置文件:动态修改各种配置参数,支持在线集群管理
  2. Fair Scheduler特点:
    • 资源公平共享:在每个队列内部,选择应用程序时默认采用Fair策略,即队列中n个应用程序,每个应用程序可以得到1/n的资源
    • 支持资源抢占:先等待再强制回收
    • 负载均衡:用户除了可以自定义负载均衡机制,还可以使用默认的基于任务数目的均衡机制,尽可能将系统中的任务均匀的分配到各个节点上
    • 调度策略配置灵活:管理员可以为每个队列单独设置调度策略:FIFO、Fair、DRF三种
    • 提高小应用程序响应时间:即第一点提到的,Fair策略可以使小应用程序快速获取资源并运行完成
  3. 两者比较:
    • 大体思路相同:
      1. 处理心跳信息:
        • 第一类信息:最新启动的Container:资源调度器通知RM,将对应的Container从超时监控队列中删除
        • 第二类信息:运行完成的Container:回收资源,进行分配
      2. 资源分配:
        • 当NM有运行完成的资源上报时,RS将按照指定的调度策略,从层级队列的树根遍历,依次选择队列、应用程序、Container请求进行资源分配(调度结果可能是一个或多个Container请求),即所谓的三级资源分配策略
    • 三级资源分配策略不同点:
      1. 队列选择(从树形层级结构中选择叶子队列):
        • CS根据资源使用率(已使用资源量/队列资源容量)排序选择
        • FS按照指定策略排序选择(FIFO、Fair、DRF)
      2. 应用程序选择(从叶子队列中选择APP):
        • CS按照提交时间排序选择
        • FS默认按照Fair策略排序选择
      3. Container请求选择(同一个应用程序内部有多个子任务,对应多个资源请求):
        • CS按照优先级/本地性进行选择
        • FS同上
    • 随着两者功能逐步完善,两者同质化严重,基本相同,但因为Fair Scheduler比Capacity Scheduler多了特点<调度策略配置灵活>,即每个队列有三种调度策略选择,所以可以说FS具备CS所有的功能

思考问题

  1. 为什么采用层级队列组织方式,对“多用户多队列”的理解:
    • 从用户角度管理:因为不同用户,可能有不同的权限,对提交的应用程序的QoS要求不同,这时便可以把用户按照权限或QoS要求分类放置到不同的队列中进行分类管理
    • 从应用程序角度管理:因为不同的应用程序有不同的特点和要求,对资源的需求也不同,这时便可以把应用程序按照特点或资源需求分类放置在不同的队列中分类管理(其实还是对用户分类,因为只能对队列设定可以提交任务的用户)
    • 从资源的角度管理:如果是单队列,可能出现某个用户或某个应用程序霸占整个集群资源的情况,无法均衡地支持多用户多应用程序并行,这时便可以给不同的队列设定不同的资源上下限,进行资源分配管理,平衡地支持多用户多应用程序共享资源,并行运行
  2. 前一篇的疑问:AM为任务申请到资源后,为什么由AM通知NM,而不是RM通知NM:
    • 双层资源调度模型:
      • 使RM集中关注各个AM的资源分配,分担压力,功能划分
      • 下放资源分配的权限,AM内部资源分配由用户定义,灵活扩展
  3. Container只是对资源逻辑上的划分和规定,在实际使用中,如何保证严格的物理划分或隔离?
  4. 用户提交的应用程序和应用程序提交的内部任务,使用的都是这种层级队列吗?同一个吗?
  5. 通过对两种调度器三级资源分配策略的分析,可以发现在选择Container请求时,好像并没有检查将要分配出去的Container是否满足请求中的需求量,是这样吗?

从零爬Hadoop系列_2-《Hadoop技术内幕2》ResourceManager

发表于 2016-07-24   |   分类于 Hadoop   |     |   阅读次数

RM剖析

内部架构

从前边YARN的工作流程图中可以看到,RM作为一个处理中心,分别需要和Client、NM、AM交互做处理,那RM是怎么做到这些交互的呢?其实很简单,从面向对象的角度理解,RM作为一个综合的处理中心,是一个大部门,所以在RM内部,又按照服务类别细分了很多“专一”的模块,每个模块作为服务或事件调度器对外提供访问接口,所有这些访问接口组合起来才形成了上边工作流程图中的各种交互。其中每个模块内部还能继续功能细分,直到把单一功能落实到具体的类或接口中,总的内部架构图如下:
RM内部架构图

模块简介:

  1. Client交互模块:
    • ClientRMService:为普通用户提供服务,如提交应用、终止应用、获取应用运行状态等
    • AdminService:为管理员提供了一套独立的服务接口,防止大量普通用户请求使得管理命令饿死,如动态更新节点列表、更新ACL列表等
    • WebApp:Web界面,友好地展示集群资源使用情况和应用运行状态等信息
  2. NM管理模块:
    • NMLivelinessMonitor:监控NM是否活着
    • NodesListManager:维护正常节点和异常节点列表
    • ResourceTrackerService:处理来自NM的请求,主要包括注册和心跳两种请求
  3. AM管理模块:
    • AMLivelinessMonitor:监控AM是否活着
    • ApplicationMasterLauncher:与NM通信,要求它为某个应用启动AM
    • ApplicationMasterService:处理来自AM的请求,主要包括注册和心跳两种请求
  4. Application管理模块:
    • ApplicationACLsManager:管理应用程序访问权限,查看权限和修改权限
    • RMAppManager:管理应用程序的启动(提交和后续对象的创建)和关闭
    • ContainerAllocationExpirer:AM没有在规定时间内在对应的NM上启动新分配的Container,则RM强制回收,是否回收由该类决定和执行
  5. 状态机管理模块:状态机维护着有状态对象的生命周期,RM中共维护4类:
    • RMApp:维护的是同一个Application启动的所有运行实例的生命周期,从启动到运行结束
    • RMAppAttempt:app运行实例的每次启动称为一次运行尝试,该类维护着一次运行尝试的生命周期,从启动到运行结束
    • RMContainer:维护一个Container的运行周期,从创建到运行结束
    • RMNode:维护一个NM的生命周期,从启动到运行结束
  6. 安全管理模块:
    • 认证:同时采用Kerberos和Token两种技术,保证各个组件之间通信内容的合法性
    • 授权:访问控制列表ACL
  7. 资源分配模块:
    • ResourceScheduler:
      • 批处理调度器:FIFO
      • 多用户调度器
        • Fair Scheduler
        • Capacity Scheduler

容错机制:

  1. AM容错:RM负责监控AM的运行状态,若运行失败或超时,会重新分配资源并重启它
  2. NM容错:NM定时向RM发送心跳,若超时,则NM上的Container状态置为失败,并交由对应的AM处理其中的任务
  3. Container容错:即前边提到的ContainerAllocationExpirer负责的超时未启动处理
  4. RM容错:基于共享存储的HA解决方案,YARN采用基于Zookeeper的方案
    • 主备切换分为手动和自动
    • HA(High Availability)需要考虑的问题:
      • 脑裂:
        • 共享存储隔离:确保只有一个Master往共享存储中写数据
        • 客户端隔离:确保只有一个Master可以响应客户端的请求
        • Slave隔离:确保只有一个Master可以向Slave下发命令
      • 切换对外透明:多次连接失败后换一个连接

常见行为分析

因为RM相当于YARN整个系统的核心,具备很多功能,每个功能都是基于事件在各个组成结构之间驱动的,所以并没有一个固定或统一的处理流程,只能针对某一个功能来说,比如:

  • 启动AM
  • 申请和分配Container
  • 杀死AM
  • Container超时
  • AM超时
  • NM超时

流程复杂,这里不再详述,建议回去翻书,总之一定要结合几个常见行为的分析,从中理解:服务化、基于事件驱动、状态机这三者在其中的应用,以及相比之前的直接函数调用,这三者的优势和带来的改进。
RM中的重头:资源管理器,将在下篇博文详细介绍。

思考问题

想不通的不要急,后续了解多了自然就明白了(带着问题看书懂得更多)。

  1. YARN的工作流程第5步:
    • 为什么AM为任务申请到资源以后,不是RM通知对应的NM启动对应的Container?
    • 怎么保证AM没有撒谎?比如AM并没有向RM申请资源,绕过RM直接通知NM启动任务?
  2. YARN的工作流程第6步,为什么运行脚本而不是直接运行命令?

从零爬Hadoop系列_1-《Hadoop技术内幕2》基础篇

发表于 2016-07-24   |   分类于 Hadoop   |     |   阅读次数

基础篇

MRv1到YARN

  1. MRv1主要是以MR为主的计算框架,而MRv2主要是针对MRv1的缺陷改进而来的,以YARN为主的轻量级弹性计算平台;
  2. MRv1的缺陷:
    • 扩展性差:JobTracker兼备资源管理和作业控制;
    • 可靠性差:master单点故障;
    • 资源利用率低:粗粒度的划分单位,任务之间不共享;
    • 无法支持多种计算框架:只有基于磁盘的离线计算框架MR,不能满足多种需求;
  3. YARN的诞生背景:
    • 基于数据密集型应用的计算框架层出不穷:
      • MR:离线处理;
      • Storm:在线处理;
      • Spark:迭代式处理;
      • S4:流式处理;
    • 各种框架各有所长,在同一个公司中,多种框架可能被同时采用,如网页建立索引用MR,自然语言处理/数据挖掘用Spark等,考虑到成本等,又希望把所有框架部署在一个共享集群中,而非各占一个独立集群,而且需要在对共享资源统一管理使用的同时,保证各个任务的隔离性,急需轻量级弹性计算平台。
  4. 共享集群的好处:
    • 资源利用率高:多种框架共享资源,统一管理,不会出现分配不均或某些紧缺而某些空闲的问题;
    • 运维成本低:管理员成本和硬件成本;
    • 数据共享:减小数据移动带来的成本;
  5. 一个框架一个集群 到 多个框架共享集群:
    共享集群

YARN的组成结构和流程

  1. YARN基本组成结构:
    • ResourceManager(RM):全局资源管理器,负责资源管理和分配;
      • Schduler:纯调度器,只负责根据各个应用程序的资源需求进行资源分配;
      • ApplicationManager(ASM):负责管理整个系统中所有应用程序;
    • ApplicationMaster(AM):用户提交的每个应用程序均包含一个AM,主要功能:
      • 与Scheduler协商获取资源(Container);
      • 将得到的任务进一步分配给内部的任务;
      • 与NM通信以启动/停止任务;
      • 监控所有任务运行状态,并在任务运行失败时重新为任务申请资源以重启任务;
    • NodeManager(NM):每个节点上的资源和任务管理器,主要功能:
      • 定时向RM汇报本节点上的资源使用情况和各个Container的运行状态;
      • 接受并处理来自AM的Container启动/停止等请求;
    • Container:资源抽象,封装某个节点上的多维度资源,如内存、CPU、磁盘等
  2. YARN工作流程:
    • 步骤1:用户向YARN提交应用程序,其中包括AM程序、启动AM的命令、用户程序等;
    • 步骤2:RM为该应用程序分配第一个Container,并与对应的NM通信,要求它在这个Container中启动该AM;
    • 步骤3:AM首先向RM注册,这样用户可以通过RM查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它们的运行状态,直到运行结束,即重复步骤4~7;
    • 步骤4:AM采用轮询的方式,通过RPC协议向RM申请和领取资源;
    • 步骤5:一旦AM申请到资源后,便与对应的NM通信,要求它启动任务;
    • 步骤6:NM为任务设置好运行环境后,将任务启动命令写到一个脚本中,通过运行该脚本启动任务;
    • 步骤7:各个任务通过某个RPC协议向AM汇报自己的状态和进度,以便AM随时掌握各个任务的运行状态,从而可以在任务失败时重启任务;
    • 步骤9:应用程序运行完成后,AM向RM注销并关闭自己;
    • 如下图:
      YARN工作流程
  3. YARN的理解角度:
    • 多线程并行编程:
      • YARN:云操作系统,为应用程序启动AM;
      • AM:主线程,负责应用程序内部的数据切分、任务分配等,并启动各个Task;
      • Task:子线程,仅负责自己的计算任务,完成即结束退出;
      • 当所有子线程(Task)结束以后,主线程(AM)结束退出;
    • 资源管理器;
    • 云计算:YARN可以看做PAAS层,为不同类型的应用程序提供统一的管理和调度;

YARN基础库

RPC

  1. Hadoop RPC(集群各组件之间的通信方式)总体架构:
    • 序列化层:结构化对象转为字节流便于网络传输或持久存储,主要用于请求中的参数和应答跨机器传输;
    • 函数调用层:定位要调用的函数并执行该函数,Hadoop RPC采用Java反射机制和动态代理实现;
    • 网络传输层:描述了Client和Server之间消息传输的方式,Hadoop RPC采用基于TCP/IP的Socket机制;
    • 服务器端处理框架:描述了Client和Server之间信息交互的方式,直接决定服务器端的并发处理能力,Hadoop RPC采用基于Reactor设计模式的事件驱动I/O模型;
  2. YARN RPC:可以集成多种RPC框架,如Protocol Buflers、Thrift、Avro等;
  3. 对RPC的理解和实现,可以通过查看具体的例子进行理解,比如NM的心跳函数;

服务库(使得YARN低耦合、高内聚、设计简单、易维护)

  1. 对于生命周期较长的对象,YARN采用了基于服务的对象管理模型对其进行管理,几个特点:
    • 每个被服务化的对象分为4个状态:NOTINITED、INITED、STARTED、STOPPED;
    • 任何服务状态变化都可以触发另外一些动作;
    • 可以通过组合的方式对任意服务进行组合,以便统一管理;
  2. 在YARN中,RM和NM属于组合服务,它们内部包含多个单一服务和组合服务,以实现对内部多种服务的统一管理;

事件库(使得YARN低耦合、高内聚、设计简单、易维护)

  1. 为了构建基于事件驱动的并发模型,YARN将各种处理逻辑抽象成事件和对应的事件调度器,并把每类事件的处理过程分割成多个步骤,用有限状态机表示;
  2. 处理过程:
    • 处理请求作为事件进入系统;
    • 由中央异步调度器负责传递给对应的事件调度器;
    • 事件调度器有两种处理:
      • 可能将该事件转发给另外一个事件调度器;
      • 也可能交给一个带有有限状态机的事件处理器,其处理结果也以事件的形式输出给中央异步调度器;
    • 新的事件会再次被中央异步调度器转发给下一个事件调度器,直至处理完成(到达终止条件)。
  3. 在YARN中,所有核心服务实际上都是一个中央异步调度器,包括RM、NM、AM等,它们维护了事先注册的事件和事件处理器,并根据接收的事件类型驱动服务的运行;

状态机库(使得YARN设计架构更清晰)

  1. 如上所述,在YARN中,事件的处理过程被分割成多个步骤,用有限状态机表示,换言之,有限状态机维护着有状态对象的生命周期;
  2. 在YARN中,每种状态转换由一个四元组表示,分别是转换前状态preState、转换后状态postState、事件event和回调函数hook,表示状态机在preState状态下,接收到事件event后,执行回调函数hook,并在执行完成后将状态转换为postState。
  3. YARN定义了三种状态转换方式:
    • 一个初态、一个终态、一种事件;
    • 一个初态、多个终态、一种事件,终态由hook返回值确定;
    • 一个初态、一个终态、多种事件;

从零爬Hadoop系列_0-我听说的Hadoop

发表于 2016-07-23   |   分类于 Hadoop   |     |   阅读次数

前言

在两年前入学就听舍友说这些高大上的东西,然而两年过去了,前一段阿里面试问及依然一问三不知。最近在华为实习,有幸借此机会接触学习大数据,三周过去获益匪浅。不仅仅是学到了知识,而且还学到并深刻体会到学习能力和学习方法的重要性。从看书到写笔记,再把笔记串联起来整理成博文,不仅记录学习历程,方便以后回头复习,而且使自己理解得更透彻,而不是蒙混过关。所以我把最近学习的笔记,结合自己的理解整理成一系列博文,主要包括读书笔记、环境搭建、使用说明、以及一些源码理解,旨在二次理解、记录存档和分享。

什么是Hadoop

近几年大数据火得不行,平时我们可能多多少少会听到一些相关的东西,比如Hadoop、MapReduce、Spark什么的,但还真没仔细了解过都是些什么东西,有什么用。所以在开始学习之前,先来看一下我们要学的是什么。

What Is Apache Hadoop?
The Apache™ Hadoop® project develops open-source software for reliable, scalable, distributed computing.
The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models. It is designed to scale up from single servers to thousands of machines, each offering local computation and storage. Rather than rely on hardware to deliver high-availability, the library itself is designed to detect and handle failures at the application layer, so delivering a highly-available service on top of a cluster of computers, each of which may be prone to failures.

简单地总结一下就是借助Hadoop,我们可以很方便的把廉价普通的机器组成集群,然后通过简单的编程模型实现分布式地大数据计算处理,而且有容错机制保证高可靠性。不懂吗?接着往下看。

主要模块

Hadoop有很多版本,其中从Hadoop1升级到Hadoop2的变化最大。可以说,Hadoop1只是一个以MapReduce为主的计算框架,而Hadoop2则进化成一个以Yarn为主的弹性计算平台,侧重于集群的资源管理,同时可以集成包括MapReduce在内的众多计算框架。Hadoop2主要包括以下四个模块:

The project includes these modules:
Hadoop Common: The common utilities that support the other Hadoop modules.
Hadoop Distributed File System (HDFS™): A distributed file system that provides high-throughput access to application data.
Hadoop YARN: A framework for job scheduling and cluster resource management.
Hadoop MapReduce: A YARN-based system for parallel processing of large data sets.

如果你和我一样对大数据和Hadoop是个小白,那你可能需要先弄明白集群是怎么运作的。
什么是集群呢?其实很简单,通俗点讲,就是由一群机器组成的一个整体,而且这个整体和其他所有团体一样,拥有自己的内部架构,根据责任划分“部门”,自然也就有Boss和干活的小喽喽。Boss作为集群整体对外的任务承接人,拿到任务以后,再根据内部规则有条不紊地分配下发,具体到各个小喽喽都有自己的一小部分任务做,大家都完成以后整个任务也就完成了,人多力量大嘛。听起来是不是很像我们码农在公司搬砖一样呢?其实就是一样的,这种架构就是我们常听到的Master-Slave(你有没有觉得我们曾经学过的很多东西其实都不是什么新东西,都是从我们现实世界已有的概念和规则搬过去了而已,不过也不能说不是创新)。
现在我们再来解释一下上边四个组件的作用:

  1. Hadoop Common:顾名思义,是一些公共的基础组件,主要包括RPC、事件库和状态机三部分。RPC是什么呢?Remote Process Call,远程过程调用,主要用于集群间各个机器通过网络进行通信的,是不是才反应过来?我们平时写代码顶多也就是线程通信、进程通信,那集群之间当然是网络通信了。至于事件库和状态机,可以先不细究,只用记着它们两个让整个集群的并发量上了天就可以了。
  2. HDFS:一个分布式文件系统,什么用呢?文件系统可以理解吧?存储在硬盘上的二进制数据,就是靠文件系统变成了一个个有组织的、方便操作的文件。那对于集群才说,当然需要一个分布式的文件系统,把整个集群的所有硬盘数据当成一个整体来管理使用了。怎么做到的?当然也是靠Master-Slave啦。
  3. YARN:这个是Hadoop2中最重要的角色,后续的读书笔记也主要是讲它的。前边说可以很方便的把廉价机器组成集群,通过简单的编程模型就能够实现分布式大数据处理,就是靠它实现的。
  4. MapReduce:这个不用再多说了吧,网上解释的例子一大堆,反正通过它,你可以只用写很少量的代码实现分布式计算。

作为开场白,就介绍这么多吧,后续就要开始读书笔记了,看的是董西成的《Hadoop技术内幕:深入解析YARN架构设计和实现原理》。读完整个书再看源码,才意识到如果有人写得代码可以让人专门出书来解读,而且不是瞎吹,硬生生解读成一本书,那是要有多厉害。不过话说回来,我们学的所有代码好像都有对应的书在解读,所以大牛还是很多的,随便看一个都能获益匪浅。

12
ksni88

ksni88

15 日志
5 分类
23 标签
Links
  • 海神
  • 杭城梦少
© 2016 ksni88
由 Hexo 强力驱动
主题 - NexT.Pisces