本小节介绍应用程序的 ApplicationMaster 在 NodeManager 成功启动并向 ResourceManager 注册后,向 ResourceManager 请求资源(Container)到获取到资源的整个过程,以及 ResourceManager 内部涉及的主要工作流程。

一、整体流程

整个过程可看做以下两个阶段的送代循环:

  • 阶段1 ApplicationMaster 汇报资源需求并领取已经分配到的资源;
  • 阶段2 NodeManager 向 ResourceManager 汇报各个 Container 运行状态,如果 ResourceManager 发现它上面有空闲的资源,则进行一次资源分配,并将分配的资源保存到对应的 应用程序数据结构中,等待下次 ApplicationMaster 发送心跳信息时获取(即阶段1)。

一)AM 汇报心跳

1、ApplicationMaster 通过 RPC 函数 ApplicationMasterProtocol#allocate 向 ResourceManager 汇报资源需求(由于该函数被周期性调用,我们通常也称之为“心跳”),包括新的资源需求描述、待释放的 Container 列表、请求加入黑名单的节点列表、请求移除黑名单的节点列表等。

public AllocateResponse allocate(AllocateRequest request) {
// Send the status update to the appAttempt.
// 发送 RMAppAttemptEventType.STATUS_UPDATE 事件
this.rmContext.getDispatcher().getEventHandler().handle(
new RMAppAttemptStatusupdateEvent(appAttemptId, request.getProgress())); // 从 am 心跳 AllocateRequest 中取出新的资源需求描述、待释放的 Container 列表、黑名单列表
List<ResourceRequest> ask = request.getAskList();
List<ContainerId> release = request.getReleaseList();
ResourceBlacklistRequest blacklistRequest = request.getResourceBlacklistRequest(); // 接下来会做一些检查(资源申请量、label、blacklist 等) // 将资源申请分割(动态调整 container 资源量)
// Split Update Resource Requests into increase and decrease.
// No Exceptions are thrown here. All update errors are aggregated
// and returned to the AM.
List<UpdateContainerRequest> increaseResourceReqs = new ArrayList<>();
List<UpdateContainerRequest> decreaseResourceReqs = new ArrayList<>();
List<UpdateContainerError> updateContainerErrors =
RMServerUtils.validateAndSplitUpdateResourceRequests(rmContext,
request, maximumCapacity, increaseResourceReqs,
decreaseResourceReqs); // 调用 ResourceScheduler#allocate 函数,将该 AM 资源需求汇报给 ResourceScheduler
// (实际是 Capacity、Fair、Fifo 等实际指定的 Scheduler 处理)
allocation =
this.rScheduler.allocate(appAttemptId, ask, release,
blacklistAdditions, blacklistRemovals,
increaseResourceReqs, decreaseResourceReqs);
}

2、ResourceManager 中的 ApplicationMasterService#allocate 负责处理来自 AM 的心跳请求,收到该请求后,会发送一个 RMAppAttemptEventType.STATUS_UPDATE 事件,RMAppAttemptImpl 收到该事件后,将更新应用程序执行进度和 AMLivenessMonitor 中记录的应用程序最近更新时间。

3、调用 ResourceScheduler#allocate 函数,将该 AM 资源需求汇报给 ResourceScheduler,实际是 Capacity、Fair、Fifo 等实际指定的 Scheduler 处理。

CapacityScheduler#allocate 实现为例:

// CapacityScheduler#allocate
public Allocation allocate(ApplicationAttemptId applicationAttemptId,
List<ResourceRequest> ask, List<ContainerId> release,
List<String> blacklistAdditions, List<String> blacklistRemovals,
List<UpdateContainerRequest> increaseRequests,
List<UpdateContainerRequest> decreaseRequests) { // Release containers
// 发送 RMContainerEventType.RELEASED
releaseContainers(release, application); // update increase requests
LeafQueue updateDemandForQueue =
updateIncreaseRequests(increaseRequests, application); // Decrease containers
decreaseContainers(decreaseRequests, application); // Sanity check for new allocation requests
// 会将资源请求进行规范化,限制到最小和最大区间内,并且规范到最小增长量上
SchedulerUtils.normalizeRequests(
ask, getResourceCalculator(), getClusterResource(),
getMinimumResourceCapability(), getMaximumResourceCapability()); // Update application requests
// 将新的资源需求更新到对应的数据结构中
if (application.updateResourceRequests(ask)
&& (updateDemandForQueue == null)) {
updateDemandForQueue = (LeafQueue) application.getQueue();
} // 获取已经为该应用程序分配的资源
allocation = application.getAllocation(getResourceCalculator(),
clusterResource, getMinimumResourceCapability()); return allocation;
}

4、ResourceScheduler 首先读取待释放 Container 列表,向对应的 RMContainerImpl 发送 RMContainerEventType.RELEASED 类型事件,杀死正在运行的 Container;然后将新的资源需求更新到对应的数据结构中,之后获取已经为该应用程序分配的资源,并返回给 ApplicationMasterService。

二)NM 汇报心跳

1、NodeManager 将当前节点各种信息(container 状况、节点利用率、健康情况等)封装到 nodeStatus 中,再将标识节点的信息一起封装到 request 中,之后通过RPC 函数 ResourceTracker#nodeHeartbeat 向 ResourceManager 汇报这些状态。

// NodeStatusUpdaterImpl#startStatusUpdater
protected void startStatusUpdater() { statusUpdaterRunnable = new Runnable() {
@Override
@SuppressWarnings("unchecked")
public void run() {
// ...
Set<NodeLabel> nodeLabelsForHeartbeat =
nodeLabelsHandler.getNodeLabelsForHeartbeat();
NodeStatus nodeStatus = getNodeStatus(lastHeartbeatID); NodeHeartbeatRequest request =
NodeHeartbeatRequest.newInstance(nodeStatus,
NodeStatusUpdaterImpl.this.context
.getContainerTokenSecretManager().getCurrentKey(),
NodeStatusUpdaterImpl.this.context
.getNMTokenSecretManager().getCurrentKey(),
nodeLabelsForHeartbeat); // 发送 nm 的心跳
response = resourceTracker.nodeHeartbeat(request);

2、ResourceManager 中的 ResourceTrackerService 负责处理来自 NodeManager 的请 求,一旦收到该请求,会向 RMNodeImpl 发送一个 RMNodeEventType.STATUS_UPDATE 类型事件,而 RMNodelmpl 收到该事件后,将更新各个 Container 的运行状态,并进一步向 ResoutceScheduler 发送一个 SchedulerEventType.NODE_UPDATE 类型事件。

// ResourceTrackerService#nodeHeartbeat
public NodeHeartbeatResponse nodeHeartbeat(NodeHeartbeatRequest request)
throws YarnException, IOException { NodeStatus remoteNodeStatus = request.getNodeStatus();
/**
* Here is the node heartbeat sequence...
* 1. Check if it's a valid (i.e. not excluded) node
* 2. Check if it's a registered node
* 3. Check if it's a 'fresh' heartbeat i.e. not duplicate heartbeat
* 4. Send healthStatus to RMNode
* 5. Update node's labels if distributed Node Labels configuration is enabled
*/ // 前 3 步都是各种检查,后面才是重点的逻辑
// Heartbeat response
NodeHeartbeatResponse nodeHeartBeatResponse =
YarnServerBuilderUtils.newNodeHeartbeatResponse(
getNextResponseId(lastNodeHeartbeatResponse.getResponseId()),
NodeAction.NORMAL, null, null, null, null, nextHeartBeatInterval);
// 这里会 set 待释放的 container、application 列表
// 思考:为何只有待释放的列表呢?分配的资源不返回么? - 分配的资源是和 AM 进行交互的
rmNode.setAndUpdateNodeHeartbeatResponse(nodeHeartBeatResponse); populateKeys(request, nodeHeartBeatResponse); ConcurrentMap<ApplicationId, ByteBuffer> systemCredentials =
rmContext.getSystemCredentialsForApps();
if (!systemCredentials.isEmpty()) {
nodeHeartBeatResponse.setSystemCredentialsForApps(systemCredentials);
} // 4. Send status to RMNode, saving the latest response.
// 发送 RMNodeEventType.STATUS_UPDATE 事件
RMNodeStatusEvent nodeStatusEvent =
new RMNodeStatusEvent(nodeId, remoteNodeStatus);
if (request.getLogAggregationReportsForApps() != null
&& !request.getLogAggregationReportsForApps().isEmpty()) {
nodeStatusEvent.setLogAggregationReportsForApps(request
.getLogAggregationReportsForApps());
}
this.rmContext.getDispatcher().getEventHandler().handle(nodeStatusEvent);

3、ResourceScheduler 收到事件后,如果该节点上有可分配的空闲资源,则会将这些资源分配给各个应用程序,而分配后的资源仅是记录到对应的数据结构中,等待 ApplicationMaster 下次通过心跳机制来领取。(资源分配的具体逻辑,将在后面介绍 Scheduler 的文章中详细讲解)。

三、总结

本篇分析了申请与分配 Container 的流程,主要分为两个阶段。

第一阶段由 AM 发起,通过心跳向 RM 发起资源请求。

第二阶段由 NM 发起,通过心跳向 RM 汇报资源使用情况。

之后就是,RM 根据 AM 资源请求以及 NM 剩余资源进行一次资源分配(具体分配逻辑将在后续文章中介绍),并将分配的资源通过下一次 AM 心跳返回给 AM。

【深入浅出 Yarn 架构与实现】4-6 RM 行为探究 - 申请与分配 Container的更多相关文章

  1. 【深入浅出 Yarn 架构与实现】4-2 RM 管理 Application Master

    上一篇文章对 ResourceManager 整体架构和功能进行了讲述.本篇将对 RM 中管理 Application Master 的部分进行深入的讲解. 下面将会介绍 RM 与 AM 整体通信执行 ...

  2. 【深入浅出 Yarn 架构与实现】4-3 RM 管理 NodeManager

    本篇继续对 RM 中管理 NodeManager 的部分进行深入的讲解.主要有三个部分:检查 NM 是否存活:管理 NM 的黑白名单:响应 NM RPC 请求. 一.简介 在 RM 的主从结构中,最主 ...

  3. 【深入浅出 Yarn 架构与实现】4-4 RM 管理 Application

    在 YARN 中,Application 是指应用程序,它可能启动多个运行实例,每个运行实例由 -个 ApplicationMaster 与一组该 ApplicationMaster 启动的任务组成, ...

  4. 【深入浅出 Yarn 架构与实现】1-1 设计理念与基本架构

    一.Yarn 产生的背景 Hadoop2 之前是由 HDFS 和 MR 组成的,HDFS 负责存储,MR 负责计算. 一)MRv1 的问题 耦合度高:MR 中的 jobTracker 同时负责资源管理 ...

  5. 【深入浅出 Yarn 架构与实现】4-1 ResourceManager 功能概述

    前面几篇文章对 Yarn 基本架构.程序基础库.应用设计方法等进行了介绍.之后几篇将开始对 Yarn 核心组件进行剖析. ResourceManager(RM)是 Yarn 的核心管理服务,负责集群管 ...

  6. 【深入浅出 Yarn 架构与实现】3-1 Yarn Application 流程与编写方法

    本篇学习 Yarn Application 编写方法,将带你更清楚的了解一个任务是如何提交到 Yarn ,在运行中的交互和任务停止的过程.通过了解整个任务的运行流程,帮你更好的理解 Yarn 运作方式 ...

  7. 【深入浅出 Yarn 架构与实现】3-2 Yarn Client 编写

    上篇文章介绍了编写 Yarn Application 的整体框架流程,本篇文章将详细介绍其中 Client 部分的编写方式. 一.Yarn Client 编写方法 本篇代码已上传 Github: Gi ...

  8. 【深入浅出 Yarn 架构与实现】1-2 搭建 Hadoop 源码阅读环境

    本文将介绍如何使用 idea 搭建 Hadoop 源码阅读环境.(默认已安装好 Java.Maven 环境) 一.搭建源码阅读环境 一)idea 导入 hadoop 工程 从 github 上拉取代码 ...

  9. 【深入浅出 Yarn 架构与实现】2-2 Yarn 基础库 - 底层通信库 RPC

    RPC(Remote Procedure Call) 是 Hadoop 服务通信的关键库,支撑上层分布式环境下复杂的进程间(Inter-Process Communication, IPC)通信逻辑, ...

  10. 【深入浅出 Yarn 架构与实现】3-3 Yarn Application Master 编写

    本篇文章继续介绍 Yarn Application 中 ApplicationMaster 部分的编写方法. 一.Application Master 编写方法 上一节讲了 Client 提交任务给 ...

随机推荐

  1. 10分钟看懂Docker和K8S,docker k8s 区别

    10分钟看懂Docker和K8S,docker k8s 区别 2010年,几个搞IT的年轻人,在美国旧金山成立了一家名叫"dotCloud"的公司. 这家公司主要提供基于PaaS的 ...

  2. NCTF2022 - pwn 部分 wp

    总的来说我出的几题不是很难,主要是想把自己感觉有意思的一些东西分享给大家. ezlogin 程序设计周大作业稍加改编出的题目.洞在Tea里,有个数组越界写,为了避开\x00截断,我给了*可以对其进行替 ...

  3. base64解析爬取糗百

    一.缘由 这是我之前刚开始学习的时候爬取糗百的练习内容,主要练习的是bs64解析.虽然现在用的不是特别的多,但是当初的时候用起来还是非常的顺手的. 二.代码实现 #coding:utf-8 impor ...

  4. excel甘特图制作

    1.插入图表   1 1.选中数据区域(3列,如图所示)--点击插入--推荐的图表--堆积条形图 END 2.甘特图制作   1 2.点击图表工具--设计--选择数据. 轴标签区域改为--确定项目.. ...

  5. 基于U-Net网络的图像分割的MindStudio实践

    摘要:本实践是基于Windows版MindStudio 5.0.RC3,远程连接ECS服务器使用,ECS是基于官方分享的CANN6.0.RC1_MindX_Vision3.0.RC3镜像创建的. 本文 ...

  6. Python Kconfiglib初次学习

    1 参考 kconfiglib库官方介绍:kconfiglib · PyPI Kconfiglib源码:GitHub - ulfalizer/Kconfiglib: A flexible Python ...

  7. MongoDB6.0的安装「2023年」

    你好,我是悦创. 优质原文格式:https://bornforthis.cn/column/crawler/supplement/mongodb-install.html 点进去有惊喜. 吐槽,这篇博 ...

  8. Debian 软件包管理

    Debian 软件包管理 Debian 软件包管理 基础软件包管理知识 sources.list 文件格式 新手建议 档案库临时小故障 软件包依赖关系 APT 进行软件包管理 基本操作 软件包管理操作 ...

  9. elasticsearch之search template

    一.search template简介 elasticsearch提供了search template功能,其会在实际执行查询之前,对search template进行预处理并将参数填充到templa ...

  10. AI换脸实战教学(FaceSwap的使用)---------第二步Tools:处理输入数据集。

    续上篇:https://www.cnblogs.com/techs-wenzhe/p/12936809.html 第一步中已经提取出了源视频的人脸照片以及对应人脸遮罩(landmark以及其他自选遮罩 ...