深入解析yarn架构设计与技术实现-NodeManager2

深入解析yarn架构设计与技术实现-Node Manager2

状态机管理

Nodemanager中的状态机一共有三类,分别是Application,Container和 LocalizedResource。NodeManager收到一个应用的在本机的第一个container启动命令时,会创建一个Application状态机来跟踪该应用程序在该节点的状态。每个container对已一个状态机;而每个资源(jar,文件等)的下载过程均由一个状态机LocalizedResource维护和跟踪。

Application状态机

Application的状态机在package org.apache.hadoop.yarn.server.nodemanager.containermanager.application里,它主要是为了对一个节点上统一Application的container进行统一管理。Nodemanager上的Application的状态可以近似看做ResourceManager的ApplicationAttempt一个子集,并且和ResourceManager上的ApplicationAttempt状态同步。

2016-08-22-234253

这里我觉得需要提一下的就是Finishing_containers_wait状态和Application_resources_cleaningup:

  • Finishing_containers_wait: 当Application状态机收到Finish_aplication事件以后,回想各个container发送kill命令以回收他们占用的资源,这个状态是等待回收container占用的资源时所处的状态
  • Application_resources_cleaningup:Application所有container占用的资源被回收后所处的状态。

我觉得这两个状态应该是对应的ApplicationAttempt的Finishing状态。

Container状态机

container状态机维护一个container运行的全部状态,包含11个状态和10个事件,代码主要在package org.apache.hadoop.yarn.server.nodemanager.containermanager.container; 。下面是状态转化的图,具体的细节也是建议直接看书,我就不”抄书”了

2016-08-23-000620

LocalizedResource状态机

2016-08-25-224105

状态转移没什么好说的,着重说一下下载。

下载是在从init状态转移到downloading状态时,会发一个REQUEST_RESOURCE_LOCALIZATION事件。这个事件是会发给ResourceLocalizationService,ResourceLocalizationService根据资源的类型和可见性确定路径并下载他。下载是异步的(并且每个application对应着自己的下载线程),每个下载会对应一个callable的FSDownload

Container生命周期

Container启动主要分为三个部分,资源本地化,container启动和资源清理。

资源本地化

资源本地化主要是完成初始化各种服务,创建工作目录,从HDFS下载运行所需的各种资源等。资源本地化分为应用程序本地化和container本地化。应用程序本地化主要是初始化应用执行的各种服务组件,比如loghandler等,通常是在应用的第一个container启动时完成;container本地化是创建工作目录,从hdfs下载各种文件等

一个application的第一个container启动时,流程图如下,主要是分为相关组件启动和container启动两部分。其中2-5启动了日志记录组件LogHandler和资源状态追踪组件,7-12步相关目录创建和资源下载。

2016-08-26-220652

剩余container的启动相对简单,不需要处理application相关的任务,下图是剩余container启动的流程图,其中2-8步和之前第一个container启动的7-12步是相同的。

2016-08-26-220914

container运行

container运行主要分为四个步骤,涉及到运行脚本的生成,执行以及对该执行的监控,这里详细讲一下,首先上一张流程图

2016-08-26-223610

  1. cotainerImpl向ContainersLauncher服务发送Launch_container事件请求启动container
  2. ConatinerLauncher收到Launch_container时间后,为该Container创建一个callable类型的对象ContainerLaunch,并放在线程池中。ContainerLaunch会为container创建tokens文件和执行脚本文件launch_container.sh,并保存在nmPrivate中。launch_container.sh包含containersuo’xu所需的环境变量,运行状态等全部信息
  3. 准备好launch-container.sh后,containerLaunch首先向containerImpl发送一个CONTAINER_LAUNCHED事件,让他启动container监控机制,然后调用containerExecutor#launchcontainer启动container。启动的contain。containerExecutor有两类
    1. defaultContainerExecutor:用一个default_container_executor.sh以nodeManager启动者身份运行launch_container.sh
    2. 用c语言的setuid运行containerExecutor,运行身份是应用程序所属的用户身份,后面的cpu资源隔离机制与其有关
  4. containerImpl收到container——launched时间后,进一步向containersMonitorImpl服务发送一个start_monitoring_container事件,已启动对该container的内存资源监控,该containerimpl状态转换为running。由于containerExecutor#launchContainer​是阻塞式的,当脚本完成后才退出。退出后containerLauncher想containerImpl发送comtainer_exited_with_success事件,containerimple状态转为exxited_with_success,一个contain的运行阶段完成

container清理

container运行结束后,NodeManager需要回收他占用的资源,主要是container运行使用的临时目录。在这个阶段NodeManager会删除用户工作目录和NodeManager私有目录下的container文件。但是并不会删除用于存放临时输出的文件${yarn.nodemanager.local-dirs}/usercache/${user}/appcache/${appid}/output。output石凳整个application执行结束后统一删除的

同时container结束时会检查进程pid文件是否存在,存在的话证明container未退出,会强制kill了进程。

2016-08-26-222238

资源隔离

yarn对于内存采用的是线程监控方案,而对于cpu采用的是cgroup的方式实现资源隔离。

内存的资源隔离主要是基于线程监控。监控线程会每隔一段时间扫描所有运行的container进程,构造其进程树并判断其使用的内存容量。因为jvm使用fork+exec模型创建子进程,子进程会复制父进程的内存空间,yarn引用了年龄的概念。新进程年龄为0,每次检查时年龄加1,如果年龄大于1的所有进程内存超过限额或者所有年龄的进程内存超过限额的两倍,则认为使用内存超限。

对于cpu,通过cgroups的cpu子系统可以控制进程使用cpu的时间片,进而控制每个container使用cpu的比例。同时通过赋予Nodemanager进程本身root权限,让其有能力将container的启动用户修改为提交用户,可以防止container执行一些只有nodemanager用户有权执行的操作(比如杀死nodemanager进程)


本文采用创作共用保留署名-非商业-禁止演绎4.0国际许可证,欢迎转载,但转载请注明来自http://thousandhu.github.io,并保持转载后文章内容的完整。本人保留所有版权相关权利。

本文链接:http://thousandhu.github.io/2016/08/28/深入解析yarn架构设计与技术实现-NodeManager2/