Yarn源码分析之集群启动流程


本文以hadoop2.7.1的源码分析(主要是最新版本考虑更多因素,源码不够纯粹)

集群启动脚本分析

首先我们从启动hadoop集群说起,我们一般在单点hadoop启动集群一般直接使用 sbin/start-all.shsbin/stop-all.sh ,我们直接看启动脚本:

bin=`dirname "${BASH_SOURCE-$0}"`
bin=`cd "$bin"; pwd`

DEFAULT_LIBEXEC_DIR="$bin"/../libexec
HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR}
. $HADOOP_LIBEXEC_DIR/hadoop-config.sh

# start hdfs daemons if hdfs is present
if [ -f "${HADOOP_HDFS_HOME}"/sbin/start-dfs.sh ]; then
  "${HADOOP_HDFS_HOME}"/sbin/start-dfs.sh --config $HADOOP_CONF_DIR
fi

# start yarn daemons if yarn is present
if [ -f "${HADOOP_YARN_HOME}"/sbin/start-yarn.sh ]; then
  "${HADOOP_YARN_HOME}"/sbin/start-yarn.sh --config $HADOOP_CONF_DIR
fi

可以看出先后执行启动了 hadoop-config.shstart-dfs.shstart-yarn.sh 。由于本文主要探讨Yarn启动过程,所以我们直接看 start-yarn.sh

echo "starting yarn daemons"

bin=`dirname "${BASH_SOURCE-$0}"`
bin=`cd "$bin"; pwd`

DEFAULT_LIBEXEC_DIR="$bin"/../libexec
HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR}
. $HADOOP_LIBEXEC_DIR/yarn-config.sh

# start resourceManager
"$bin"/yarn-daemon.sh --config $YARN_CONF_DIR start resourcemanager
# start nodeManager
"$bin"/yarn-daemons.sh --config $YARN_CONF_DIR start nodemanager
# start proxyserver
#"$bin"/yarn-daemon.sh --config $YARN_CONF_DIR start proxyserver

可以看出Yarn先后调用 yarn-daemon.sh 启动 resourcemanager 组件;调用 yarn-daemons.sh 启动 nodemanager 组件,只不过 yarn-daemons.sh 也会调用 slaves.sh 后同样也会调用 yarn-daemon.sh ,所以我们继续分析 yarn-daemon.sh 脚本,我们看关键代码(如需看完整代码,点链接查阅即可):

...
  echo starting $command, logging to $log
    cd "$HADOOP_YARN_HOME"
    nohup nice -n $YARN_NICENESS "$HADOOP_YARN_HOME"/bin/yarn --config $YARN_CONF_DIR $command "$@" > "$log" 2>&1 < /dev/null &
    echo $! > $pid
...

可以看出最终调用 yarn 脚本,由于代码比较多,我们直接看启动 resourcemanagernodemanager 组件的代码部分:
在这里插入图片描述
从脚本可以看出,会分别调用 org.apache.hadoop.yarn.server.resourcemanager.ResourceManagerorg.apache.hadoop.yarn.server.nodemanager.NodeManager 类,调用 exec "$JAVA" -Dproc_$COMMAND $JAVA_HEAP_MAX $YARN_OPTS -classpath "$CLASSPATH" $CLASS "$@" 启动JVM进程启动常驻服务,即 ResourceManagerNodeManager 是入口类,我们以 ResourceManager 组件,继续往下分析…

注:上面介绍的一般在单节点上启动,但是在分布式情况,ResourceManager和NodeManager等分布在不同机器上,启动的进程不相同,
因此 推荐在不同节点分别启动组件 ,可以参考:

  • sbin/hadoop-daemons.sh start namenode 单独启动NameNode守护进程
  • sbin/hadoop-daemons.sh start datanode 单独启动DataNode守护进程
  • sbin/hadoop-daemons.sh start secondarynamenode 单独启动SecondaryNameNode守护进程
  • sbin/yarn-daemon.sh start resourcemanager 单独启动ResourceManager守护进程
  • sbin/yarn-daemon.sh start nodemanager 单独启动NodeManager守护进程

ResourceManager启动流程

首先我们先看下ResourceManager中的功能模块,有利于宏观掌握。ResourceManager在底层代码实现上将各个功能模块分的比较细,各个模块功能具有很强的独立性。如下图:
在这里插入图片描述
从上面启动脚本可以看出, org.apache.hadoop.yarn.server.resourcemanager.ResourceManager 是入口类的 main函数。
在这里插入图片描述
其中重点需要分析的就是上面中的 resourceManager.init(conf);resourceManager.start(); ,下面分别介绍

初始化流程

如上面的代码中的 resourceManager.init(conf); ,首先调用父类 AbstractServiceinit 函数
在这里插入图片描述
从代码,可以其服务初始化实现在 ResourceManager 类的 serviceInit 函数,如下
在这里插入图片描述

setupDispatcher() 设置的是 Always On 服务,即不考虑HA状态的一直运行的服务。其初始化的 AsyncDispatcher 内部是 有一个 阻塞的事件队列,有一个一直运行的执行线程,当阻塞队列中有事件被放入,执行线程会把事件取出来,并获取事件的类型,从事件注册器 Map<Class<? extends Enum>, EventHandler> 中获取到对应的 EventHandler 对象,并调用该对象的 dispatch 方法分发事件。这样就完成了一次异步事件调用。
createAndInitActiveServices();设置的是活动的服务上下文,即需要运行在Active RM节点上的服务,由于本文不重点解析,仅列出启动服务供参考:

  • RMSecretManagerService
  • ContainerAllocationExpirer
  • AMLivelinessMonitor
  • RMNodeLabelsManager
  • RMStateStore
  • RMApplicationHistoryWriter
  • SystemMetricsPublisher
  • NodesListManager
  • ResourceScheduler
  • SchedulerEventDispatcher
  • NMLivelinessMonitor
  • ResourceTrackerService
  • ApplicationMasterService
  • ClientRMService
  • ApplicationMasterLauncher
  • DelegationTokenRenewer

至此,配置加载和子服务初始化工作分析完了,下面我们分析,RM的启动流程

启动流程

我们回到ResourceManager类的 resourceManager.start(); 继续分析,同样首先调用父类 AbstractServicestart 函数
在这里插入图片描述
从代码,可以其服务初始化实现在 ResourceManager 类的 serviceStart 函数,如下
在这里插入图片描述
继续调用父类 CompositeServiceserviceStart 函数
在这里插入图片描述
循环启动之前启动的每个服务。
自此整个Yarn的启动过程就分析完了…

中央事件调度器-AsyncDispatcher

由于AsyncDispatcher作为Yarn的一个重要的启动常驻服务,所以我们在此分析一下。
我们都知道,Yarn是采用了基于事件驱动的并发模型:

  • 所有状态机都实现了EventHandler接口,很多服务(类名通常带有Service后缀)也实现了该接口,它们都是事件处理器。
  • 需要异步处理的事件由中央异步调度器(类名通常带有Dispatcher后缀)统一接收/派发,需要同步处理的事件直接交给相应的事件处理器。

在这里插入图片描述

事件调度就是基于 AsyncDispatcher 实现的,由上面代码分析可得,AsyncDispatcher也是在yarn启动过程中 resourceManager.init(conf); 做为服务初始化的一员,最后在 resourceManager.start(); 分别启动的,因此其启动最终也是调用 org.apache.hadoop.yarn.event.AsyncDispatcher 的函数 serviceStart 启动:

在这里插入图片描述
从代码可以看出,其实例化了一个子线程,用于异步处理事件,我们继续跟进代码,如下:
在这里插入图片描述
可以看出,在线程中循环从阻塞队列中拿出一个事件,然后分发事件处理,此过程相当于“生产者和消费者模型”中的消费者。而生产者则是由Client通过RPC提交给Yarn后,add到该阻塞队列,本文不再详述这部分。
具体的分发原理可以参考:Yarn的事件驱动模型与状态机

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值