三大步骤:资源本地化、启动并运行容器、清理资源。
校验Container Token及资源文件,创建应用实例和Container实例

校验Container Token及资源文件 //TODO

资源本地化

应用程序初始化和容器本地化。
应用程序初始化:初始各种服务组件,如日志记录LogHandler、资源状态跟踪LocalResourcesTrackerImpl。供后续容器使用,通常AM在该节点启动的第一个容器完成。
容器本地化:创建工作目录,从HDFS下载资源。

初始化

0x01
ContainerManagerImpl(YARN NM核心组件,管理所有Container的生命周期)收到AMContainerManagementProtocol.startContainers远程调用启动容器请求。创建ContainerImpl状态机。
事件发送:判断是否为第一个,如果是创建ApplicationImpl状态机并发送INIT_APPLICATION事件和INIT_CONTAINER事件。

0x02
ApplicationImpl设置ACL属性。
事件发送:LogHandler(Aggregation和NonAggregation两种实现)发送APPLICATION_STARTED事件;自己状态转为INITING。
ApplicationImpl收到INIT_CONTAINER事件后将将容器加入容器列表。此时ApplicationImpl一直INITING状态。

0x03
LogHandler创建应用日志目录、设置目录权限。
事件发送:ApplicationImpl发送APPLICATION_LOG_HANDLING_INITED事件。

0x04
ApplicationImplResourceLocalizationService发送INIT_APPLICATION_RESOURCES事件。仍然处于INITING。

0x05
ResourceLocalizationService为PRIVATE和APPLICATION资源创建资源状态跟踪器LocalResourcesTrackerImpl。PRIVATE资源对应的跟踪器如果用户创建过就不在创建了(用户名和追踪器保存在ConcurrentMap)。APPLICATION同理。PUBLIC资源有公共追踪器。
事件发送:ResourceLocalizationService将向ApplicationImpl发送APPLICATION_INITED事件。

0x06
事件发送:Application向容器列表中所有容器(到目前为止)发送INIT_CONTAINER事件通知容器初始化。ApplicationImpl状态转为INITING。

本地化

概述

主要ResourceLocalizationService组件(资源本地化服务,负责Container所需资源的本地化。它能够按照描述从HDFS上下载Container所需的文件资源,并尽量将它们分摊到各个磁盘上以防止出现访问热点)初始化各种服务组件、创建工作目录、从HDFS下载运行所需的各种资源至Container工作目录(路径为: ${yarn.nodemanager.local-dirs}/usercache/${user}/appcache//);

0x07
事件发送:每个ContainerImpl向AuxServices发送APPLICATION_INIT事件。
ContainerLaunchContext中获取资源,并保存ContainerImpl特定数据结构中。
事件发送:ResourceLocalizationService发送INIT_CONTAINER_RESOURCES事件(事件封装容器所有需下载资源)。
ContainerImpl从NEW转为LOCALIZAING。

0x08
事件发送:ResourceLocalizationService一次将容器需要每个资源封装成一个REQUEST事件,发送给对应资源跟踪器LocalResourcesTrackerImpl

0x09
LocalResourcesTrackerImpl将创建状态机LocalizedResource跟踪资源生命周期,并发送REQUEST事件转手传给LocalizedResource。此处会通过四个属性判断是否已经创建LocalizedResource(例如Map任务可能需要多个)。

0x0A
LocalizedResource检查当前状态。
事件发送:如果是LOCALIZED状态说明已经下载完成,发送RESOURCE_LOCALIZED事件给ContainerImpl
事件发送:如果是INIT或DOWNLOADING状态,则将待下载资源信息通过REQUEST_RESOURCE_LOCALIZATION事件发送给资源下载服务ResourceLocalizationServiceLocalizedResource从INIT转为DOWNLOADING。
注意:目前处于DOWNLOADING状态仍会向ResourceLocalizationService发送下载请求,但单个资源下阿紫串行,不会重复下载。

0x0B
ResourceLocalizationService把PUBLIC资源交给PublicLocalizer。
其他类型资源先判断是否为该Container创建LocalizerRunner线程,如果没有则创建,如果有直接加入下载队列。LocalizerRunner线程进一步调用ContainerExecutor.startLocalizer函数下载,该函数创建ContainerLocalizer下载客户端用LocalizationProtocol协议与ResourceLocalizaitonService通信,以获取待下载资源并下载(阻塞式串行下载)。
事件发送:下载完成后,PublicLocalizer或LocalizerRunner向LocalizedResource发送LOCALIZED事件。

0x0C
LocalizedResource进一步向ContainerImpl发送RESOURCE_LOCALIZED事件后状态从DOWNLOADING转为LOCALIZED。
ContainerImpl检查资源是否全部下载完毕,如果是则向ContainersLauncher服务发送LAUNCH_CONTAINER事件,运行Container,同时ContainerImpl从LOCALIZING转为LOCALIZED。

总结

NM上同一应用的所有ContainerImpl异步向资源下载服务ResourceLocalizationService发送待下载资源。它下载完后通知所有容器,一旦容器所有资源下载完成则进入运行容器阶段。

NM上非AM第一个启动容器

0x01 改为如下
ContainerManagerImpl收到AM启动容器请求。创建ContainerImpl状态机。
事件发送:ApplicationImpl状态机并发送INIT_CONTAINER事件。
执行0x07-0xC。
注意:如果容器启动时,前一个容器仍在下载,该容器会尝试下载前面容器还未开始下载的文件,以加快下载速度。

启动并运行容器

启动由ContainersLauncher(负责Container的具体操作,包括启动、重启、恢复和清理等)服务完成,它进一步调用ContainerExecutor(Default和Linux两种实现)。将运行所需环境变量和命令写到launch_container.sh中,并将启动该脚本命令写入container_executor.sh中(防止变量展开、特殊符号转义等),通过运行该脚本启动容器。
0x01
ContainerImplContainersLauncher服务发送LAUNCH_CONTAINER事件请求启动容器。
0x02
ContainersLauncher将为该容器创建实现Callable接口的ContainerLaunch,并放到线程池中执行:创建Tokens文件和launch_container.sh,并保存到NM私有目录${yanr.nodemanager.local-dirs}/nmPrivate中。
0x03
准备好脚本后,ContainerLaunchContainerImpl发送CONTAINER_LAUNCHED事件,启动监控容器机制,并调用ContainerExecutor.launchContainer
DefaultContainerExecutor:将launch_container.sh和Tokens文件复制到动作目录(${yarn.nodemanager.local-dirs}/usercache/${user}/appcache/${app_id}/${container_id})中,并构造default_container_executor.sh,以NM启动者用户身份运行此脚本名。
LinuxContainerExecutor:
和Default不同在于使用应用所属用户执行脚本。用C语言实现的setuid可执行程序container-executor完成。LinuxContainerExecutor还支持CPU隔离。
0x04
ContainerImpl向MonitorImpl发送START_MONITORING_CONTAINER事件,启动对容器内存使用监控。ContainerImpl状态从LOCALIZED转换为RUNNING。ContainerExecutor.launchContainer是阻塞式,脚本执行完才会退出。之后向ContainerImpl发送CONTAINER_EXITED_WITH_SUCCESS,ContainerImpl从RUNNING转换为EXITED_WITH_SUCCESS。

资源清理

ResourceLocalizationService负责清理。
通知ResourceLocalizationServiceContainerExecutor清理资源因为ResourceLocalizationService负责从HDFS下载文件到本地,ContainerExecutor为容器创建私有目录并保存临时文件(容器进程pid文件等)。

0x01
ContainerImpl收到CONTAINER_EXITED_WITH_SUCCESS事件后,向ContainerLauncher发送CLEANUP_CONTAINER和向ResourceLocalizationService发送CLEANUP_CONTAINER_RESOURCES事件。
0x02
ContainersLauncher将容器从列表中移除,并调用ContainerLaunch.cleanupContainer清理临时目录;
ResourceLocalizationService清理工作目录和NM私有目录下的Container目录,即${yarn.nodemanager.local-dirs}/usercache/${user}/appcache/${app_id}/${container_id}和${yarn.nodemanager.local-dirs}/nmPrivate/${app_id}/${container_id}。这俩目录均存放了Tokens文件和Shell运行脚本。用于存放临时数据的目录${yarn.nodemananger.local-dirs}/usercache/${user}/appcache/${app_id}/output不会删除。之后,向ContainerImpl发送CONTAINER_RESOURCES_CLEANEDUP事件。
0x03
ContainerLaunch检查容器的进程pid文件是否存在,如果存在则说明容器进程尚未退出,ContainerLaunch将调用ContainerExecutor.signalContainer向该进程发送SIGTERM和SIGKILL以强制回收资源防止资源泄露,之后删除pid文件。
ContainerImpl收到CONTAINER_RESOURCES_CLEANED_UP事件后,设置一些Metric信息,然后向ApplicaitionImpl、ContainerMonitorImpl、LogHandler发送APPLICATION_CONTAINER_FINISHED、STOP_MONIORING_CONTAINER、CONTAINER_FINISHED三个事件。这三个组件会从列表中移除该容器。移除对容器的资源使用监控并记录容器完成日志。

注意:计算任务之前有依赖关系,NM不能再容器运行完清理所有资源,尤其是参数的中间数据,只有当所有容器运行完才能清理,但NM并不知道其他NM上的容器可RM知道。当应用结束时,RM通过心跳广播给各个NM,NM清理应用所有资源。