Yarn架构
1. 简介
YARN是一个通用资源管理和调度平台 ,可为上层应用提供统一的资源管理和调度。
ResourceManager -----> 负责所有资源的监控、分配和管理
NodeManager -----> 负责自身节点的维护
ApplicationMaster -----> 负责每一个具体应用程序的调度和协调
提交作业的流程简述:
步骤一、用户向YARN提交应用程序,其中包括Application程序、启动ApplicationMaster的命令、用户程序等。
步骤二、ResourceManager为该应用程序分配第一个container,并与对应的NodeManager通讯,要求它在这个Container中启动应用程序的ApplicationMaster。
步骤三、ApplicationMaster首先向ResourceManager注册,启动成功后与 RM 保持心跳。用户可以通过ResourceManager查看应用状态,然后为各个任务申请资源,并监控他的运行状态,直至运行结束,重复4~7.
步骤四、ApplicationMaster采用轮询方式通过RPC协议向ResourceManager申请和领取资源。
步骤五、ApplicationMaster申请到资源后,便与对应的NodeManager通讯,要求启动任务。
步骤六、NodeManager为任务设置好运行环境(包含环境变量、JAR包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过该脚本启动任务。
步骤七、各个任务通过某个RPC协议向ApplicationMaster汇报自己的状态和进度,以让ApplicationMaster随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。在应用程序运行过程中,用户可以随时通过RPC向ApplicationMaster查询应用程序的当前运行状态。
步骤八、应用程序运行完成后,ApplicationMaster向ResourceManager注销并关闭自己。
2. Yarn 基本架构
2.1 ResourceManager
- ResourceManager 负责整个集群的资源管理和分配,是一个全局的资源管理系统。
- NodeManager 以心跳的方式向 ResourceManager 汇报资源使用情况(目前主要是 CPU 和内存的使用情况)。 RM 只接受 NM 的资源回报信息,对于具体的资源处理则交给 NM自己处理。
-
YARN Scheduler 根据 application 的请求为其分配资源,不负责 application job 的监控、追踪、运行状态反馈、启动等工作。
2.2 NodeManager
- NodeManager 是每个节点上的资源和任务管理器,负责该节点程序的运行,以及该节点资源的管理和监控 。
- NodeManager 定时向 ResourceManager 汇报本节点资源的使用情况和Container 的运行状态。
- NodeManager 接收并处理来自 ApplicationMaster 的 Container 启动、停止等各种请求。
2.3 ApplicationMaster
- 负责与RM 调度器协商以获取资源。
- 与 NM 通信以启动 停止任务。
- 监控所有任务运行状态,并在任务运行失败时重新为任务申请资源以重启任务。
注:
RM 只负责监控 AM ,并在 AM 运行失败时候启动它。 RM 不负责 AM 内部任务的容错,任务的容错由 AM 完成。
3. Yarn 通讯流程
3.1、client → ResourceManager
步骤1:client通过RPC函数ApplicationClientProtocol#getNewApplicention从ResourceManager获取applicationID和最大可申请资源量。
步骤2:client通过RPC函数ApplicationClientProtocol#submitApplication 将ApplicationMaster提交到ResourcesManager上。
{ application_id, application_name, queue, user, am_container_spec[ user、resource(cpu内存)、 localResources(外部文件)、 command(启动命令shell)、 environment(环境变量) ] } |
3.2 ApplicationMaster → ResourcesManager
步骤1:ApplicationMaster通过RPC函数ApplicationMasterProtocol#registerApplicationMaster向ResourceManager注册。
{ host(本次启动节点的host), rpc_port(app本次启动对外的RPC端口号), tracking_url(appmster对外提供的追踪weburl), } |
一旦ApplicationMaster注册成功ResourceManager会为他返回一个RegisterApplicationMasterResponce类型的返回值,该对象包含应用程序可申请的最大资源、应用程序访问控制列表等信息。
{ maximumCapability(最大可申请单个container占用的资源量), client_to_am_token_master_key(), application_ACLs:应用程序访问控制列表 } |
步骤2:ApplicationMaster通过RPC函数ApplicationMasterProtocol#allocate向ResourceManager申请资源(以Container表示)。
{ ask:ApplicationMaster请求的资源列表: [ priority:资源优先级, resource_name:期望资源所在节点, capability:所需的资源量 cpu内存, num_containers:需要满足条件的资源数目, relax_locality:是否松弛本地性 ], release:ApplicationMaster释放的container列表, response_id:本次通讯应答id每次+1, progress:应用程序执行进度, blacklist_request:请求加入/移除黑名单节点列表 } |
ApplicationMaster每次调用ApplicationMasterProtocol#allocate后,会收到Allocate-Response类型的返回值
{ a_m_command:am需要执行的命令,目前包含AM_RESYNC和AM_SHUTDOWN鞭尸重启和关闭;当ResourceManager重启或应用程序信息状态不一致会重启,到节点出于黑名单可能关闭 response_id:本次通讯应答ID,每次+1 allocate_container:分配给应用程序的container列表。am收到一个container会在这个运行一个任务 completed_containerstatuser:完成container状态列表。该列表中的container所处的状态可能是运行成功、失败、被杀 limit:目前集群可用的资源总量 updated_nodes:当前集群所有节点运行状态列表 num_cluster_nodes:当前集群可用节点总数 preempt:资源抢占信息。当ResourceManager将要抢占某个应用程序资源时,会提前发送一个资源列表让ApplicationMaster主动释放这些资源,如果ApplicationMaster在一定时间内未释放资源将强制回收.[ strictContract:必须释放的container列表 contract:它包含资源总量和container列表 ] nm_tokens(nodemanager token) } |
步骤3:ApplicationMaster通过RPC函数ApplicationMasterProtocol#finishApplicationMaster告诉ResourceManager应用程序执行完毕并退出。当ApplicationMaster运行完毕后,会调用ApplicationMasterProtocol#finishApplicationMaster通知ResourceManager,该RPC函数的参数类型为FinishApplicationMasterRequest如要包含以下字段。
{ diagnosis:诊断信息。当ApplicationMaster运行失败时,会记录错误原因以便于后期诊断。 tracking_url:ApplicationMaster对外提供的追踪WebURL。 final_application_status:ApplicationMaster最终所处状态。APP_UNDEFINED(未定义)、APP_SUCCEEDED(运行成功)、APP_FAILED(运行失败)、APP_KILLED(被杀死) } |
成功执行该RPC函数后,ApplicationMaster将收到一个FinishApplicationMasterResponse类型的返回值,目前没有任何信息。
ApplicationMaster将重复步骤2,不断为应用程序申请资源,直到资源得到满足或者整个应用程序运行完成。
3.3ApplicationMaster → NodeManager
步骤1:ApplicationMaster将申请到的资源二次分配给内部的任务,并通过RPC函数ContainerManagementProtocol#startContainer与对应的NodeManager通讯以启动Container(包含任务描述、资源描述等信息),该函数的参数类型startContainerRequest,主要包含一个类型为startContainerRequest的字段。
{ container_launch_context:封装了Container执行环境,主要是以下字段。 [ localResource:container执行所需的本地资源,如字典文件、JAR包或可执行文件等,以keyvalue格式保存。 tokens:container执行所需的各种Token service_data:附属服务所需的数据,以keyvlalue格式保存 environment:Container所需的执行环境变量,以keyvalue格式保存 command:Container执行命令,需要是一条Shell命令。 application_ACLs:应用程序访问控制列表,以keyvalue格式保存。 ] container_token:container启动时的安全令牌 } |
ContainerManagementProtocol#srartContainer执行成功后,会收到一个StartContainersResponse类型的返回值,包含以下字段:
{ services_meta_data:附属服务返回的元数据信息。 succeeded_requests:成功运行的Container列表。 failed_requests:运行失败的Container列表 } |
步骤2:为了事先掌握各个Container运行状态,ApplicationMaster可通过RPC函数ContainerManagementProtocol#getContainerStatus向NodeManager询问Container运行状态,一旦发现某个Container运行失败,ApplicationMaster可尝试重新为对应的任务申请资源
步骤3:一旦一个Container运行完成后,ApplicationMaster可通过RPC函数ContainerManagementProtocol#stopContainer释放Container。注意YARN是一个资源管理系统,它不仅负责分配资源,还负责回收资源。当一个Container运行完成后,它会主动确认Container是否将对应的资源释放了,也就是说任何一个Container运行结束后(此时Container可能已经退出且释放资源),ApplicationMaster必须调用RPC函数ContainerManagementProtocol#stopContainer释放Container(确保资源真的释放)。