一、概述

    本文将介绍ResourceManager在Yarn中的功能作用,从更细的粒度分析RM内部组成的各个组件功能和他们相互的交互方式。

二、ResourceManager的交互协议与基本职能

1、ResourceManager交互协议

在整个Yarn框架中主要涉及到7个协议,分别是ApplicationClientProtocol、MRClientProtocol、ContainerManagementProtocol、ApplicationMasterProtocol、ResourceTracker、LocalizationProtocol、TaskUmbilicalProtocol,这些协议封装了各个组件交互的信息。ResourceManager现实功能需要和NodeManager以及ApplicationMaster进行信息交互,其中涉及到的RPC协议有ResourceTrackerProtocol、ApplicationMasterProtocol和ResourceTrackerProtocol。

  • ResourceTracker

NodeManager通过该协议向ResourceManager中注册、汇报节点健康情况以及Container的运行状态,并且领取ResourceManager下达的重新初始化、清理Container等命令。NodeManager和ResourceManager这种RPC通信采用了和MRv1类似的“pull模型”(ResourceManager充当RPC server角色,NodeManager充当RPC client角色),NodeManager周期性主动地向ResourceManager发起请求,并且领取下达给自己的命令。

  • ApplicationMasterProtocol

    应用程序的ApplicationMaster同过该协议向ResourceManager注册、申请和释放资源。该协议和上面协议同样也是采用了“pull模型”,其中在RPC机制中,ApplicationMaster充当RPC client角色,ResourceManager充当RPC server角色。

  • ApplicationClientProtocol

  • 客户端通过该协议向ResourceManager提交应用程序、控制应用程序(如杀死job)以及查询应用程序的运行状态等。在该RPC 协议中应用程序客户端充当RPC client角色,ResourceManager充当RPC server角色。

整理一下ResourceManager与NodeManager、ApplicationMaster和客户端RPC协议交互的信息:

上图中的ResourceTrackeServer、ApplicationMasterService 、ClientRMServer是ResourceManager中处理上述功能的组件。

1、ResourceManager基本职能

ResourceManager基本职能概括起来就以下几方面:

  • 与客户端进行交互,处理来自于客户端的请求,如查询应用的运行情况等。

  • 启动和管理各个应用的ApplicationMaster,并且为ApplicationMaster申请第一个Container用于启动和在它运行失败时将它重新启动。

  • 管理NodeManager,接收来自NodeManager的资源和节点健康情况汇报,并向NodeManager下达管理资源命令,例如kill掉某个container。

  • 资源管理和调度,接收来自ApplicationMaster的资源申请,并且为其进行分配。这个是它的最重要的职能。

三、ResourceManager内部组成架构分析

    ResourceManager在底层代码实现上将各个功能模块分的比较细,各个模块功能具有很强的独立性。下图所示的是ResourceManager中的大概的功能模块组成:

1、用户交互模块

用户交互模块即上图显示的User Service管理模块。在这里边还可以看到根据不同的用户类型启用了不同的服务进行处理,AdminService处理管理员相关请求,ClientRMService处理普通客户相关请求,这样使得管理员不会因为普通客户请求太多而造成堵塞。下面看看这2个服务的具体实现代码:

  • ClientRMService

public class ClientRMService extends AbstractService implements
ApplicationClientProtocol {
private static final ArrayList<ApplicationReport> EMPTY_APPS_REPORT = new ArrayList<ApplicationReport>(); private static final Log LOG = LogFactory.getLog(ClientRMService.class); final private AtomicInteger applicationCounter = new AtomicInteger();
final private YarnScheduler scheduler;//调度器
final private RMContext rmContext;//RM上下文对象,其包含了RM大部分运行时信息,如节点列表、队列列表、应用程序列表等
private final RMAppManager rmAppManager;//app管理对象 private Server server;//一个RPC Server
protected RMDelegationTokenSecretManager rmDTSecretManager; private final RecordFactory recordFactory = RecordFactoryProvider.getRecordFactory(null);
InetSocketAddress clientBindAddress;
//访问控制对象,例如,一些应用程序在提交时设置了查看权限的话,其他普通用户就无法查看。
private final ApplicationACLsManager applicationsACLsManager;
private final QueueACLsManager queueACLsManager;
......
@Override
protected void serviceStart() throws Exception {
Configuration conf = getConfig();
YarnRPC rpc = YarnRPC.create(conf);
this.server = //实现RPC协议ApplicationClientProtocol
rpc.getServer(ApplicationClientProtocol.class, this,
clientBindAddress,
conf, this.rmDTSecretManager,
conf.getInt(YarnConfiguration.RM_CLIENT_THREAD_COUNT,
YarnConfiguration.DEFAULT_RM_CLIENT_THREAD_COUNT)); // Enable service authorization?
if (conf.getBoolean(
CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHORIZATION,
false)) {
refreshServiceAcls(conf, new RMPolicyProvider());
} this.server.start();
......
}

从上面ClientRMService的基本代码架构我们可以看出:

(1)ClientRMService是一个RPC Server,主要为来自于普通客户端的各种RPC请求。从代码实现的角度看,它是ApplicationClientProtocol协议的一个实现。

(2)之前我们已经说了,普通用户可以通过该服务来获得正在运行应用程序的相关信息,如进度情况、应用程序列表等。上面代码中都将ResourceManager运行信息封装在RMContxt接口中了,下面来看看这个接口的一个实现对象RMContextImpl:

public class RMContextImpl implements RMContext {
//中央异步调度器。RM中的各个服务和组件以及它们处理和输出的事件类型都是通过中央异步调度器组织在一起的,这样可以有效提高系统的吞吐量。
private final Dispatcher rmDispatcher; private final ConcurrentMap<ApplicationId, RMApp> applications//应用程序列表
= new ConcurrentHashMap<ApplicationId, RMApp>(); private final ConcurrentMap<NodeId, RMNode> nodes//节点列表
= new ConcurrentHashMap<NodeId, RMNode>(); private final ConcurrentMap<String, RMNode> inactiveNodes//非活跃节点列表
= new ConcurrentHashMap<String, RMNode>();
//正在运行中的AP心跳监控对象
private AMLivelinessMonitor amLivelinessMonitor;//正在运行中的AP心跳监控对象
//运行完毕后的AM心跳监控对象
private AMLivelinessMonitor amFinishingMonitor;
//用于存储ResourceManager运行状态
private RMStateStore stateStore = null;
//用于Container的超时监控,应用程序必须在一定时间内(默认10Min)使用分配到的Container去运行task,否则会被回收
private ContainerAllocationExpirer containerAllocationExpirer;
//下面变量都是与安全管理相关的对象
private final DelegationTokenRenewer delegationTokenRenewer;
private final AMRMTokenSecretManager amRMTokenSecretManager;
private final RMContainerTokenSecretManager containerTokenSecretManager;
private final NMTokenSecretManagerInRM nmTokenSecretManager;
private final ClientToAMTokenSecretManagerInRM clientToAMTokenSecretManager;
private ClientRMService clientRMService;
private RMDelegationTokenSecretManager rmDelegationTokenSecretManager;
......
}

AdminService

AdminService和ClientRMService一样都是作为RPC的服务端,它针对的处理管理员RPC请求,负责访问权限的控制,中Yarn中管理员权限的设定可以在yarn-site.xml中yarn.admi.acl项进行设置,该项的默认值是*,也就是说如果不进行设置的话就当所有的用户都是管理员。从代码上看,它是ResourceManagerAdministrationProtocol协议的一个实现:

public class AdminService extends AbstractService implements ResourceManagerAdministrationProtocol {

  private static final Log LOG = LogFactory.getLog(AdminService.class);

  private final Configuration conf;
private final ResourceScheduler scheduler;
private final RMContext rmContext;
private final NodesListManager nodesListManager; private final ClientRMService clientRMService;
private final ApplicationMasterService applicationMasterService;
private final ResourceTrackerService resourceTrackerService; private Server server;
private InetSocketAddress masterServiceAddress;
private AccessControlList adminAcl; private final RecordFactory recordFactory =
RecordFactoryProvider.getRecordFactory(null);
.....
}

AdminService代码和ClientRMService比较相似,它各类功能对象也差不多。

2、NodeManager管理

NodeManager主要是通过NMLivelinessMonitor、ResourceTrackerService和NodeListManager这3大组件来对NodeManager的生命周期、心跳处理以及黑名单处理。

(1)ResourceTrackerService

ResourceTrackerService是RPC协议ResourceTracker的一个实现,它作为一个RPC Server端接收NodeManager的RPC请求,请求主要包含2种信息,注册NodeManager和处理心跳信息。NodeManger启动时第一件事就是像ResourceManager注册,注册时NodeManager发给ResourceTrackerService的RPC包主要包含NodeManager所在节点的可用资源总量、对外开放的htpp端口、节点的host和port等信息,具体代码看ResourceTrackerService#registerNodeManager方法:

@SuppressWarnings("unchecked")
@Override
public RegisterNodeManagerResponse registerNodeManager(
RegisterNodeManagerRequest request) throws YarnException,
IOException { NodeId nodeId = request.getNodeId();//从NodeManager带来的NodeID
String host = nodeId.getHost();//NodeManager所在节点的host
int cmPort = nodeId.getPort(); //NodeManager所在节点的port
int httpPort = request.getHttpPort();//对外开放的http端口
Resource capability = request.getResource();//获得NodeManager所在节点的资源上限 RegisterNodeManagerResponse response = recordFactory
.newRecordInstance(RegisterNodeManagerResponse.class); // Check if this node is a 'valid' node
//检测节点host名称的的合法性
if (!this.nodesListManager.isValidNode(host)) {
String message =
"Disallowed NodeManager from " + host
+ ", Sending SHUTDOWN signal to the NodeManager.";
LOG.info(message);
response.setDiagnosticsMessage(message);
response.setNodeAction(NodeAction.SHUTDOWN);
return response;
}
.....
}

ResourceTrackerService另外一种功能就是处理心跳信息了,当NodeManager启动后,它会周期性地调用RPC函数ResourceTracker#nodeHeartbeat汇报心跳,心跳信息主要包含该节点的各个Container的运行状态、正在运行的Application列表、节点的健康状况等,随后ResourceManager为该NodeManager返回需要释放的Container列表、Application列表等信息。其中心跳信息处理的流程:首先,从NodeManager发来的心跳包中获得节点的状态状态信息,然后检测该节点是否已经注册过,然后检测该节点的host名称是否合法,例如是否在excluded列表中,然后再检测该次心跳是不是第一次心跳信息,这点非常重要,因为关系到心跳的重复发送与应答的相关问题。其实ResourceTrackerService和NodeManager的心跳处理机制和之前Hadoop1.x中的JobTracker与TaskTacker之间的心跳处理很相像,再然后,为NodeManager返回心跳应答信息,最后,向RMNode发送该NodeManager的状态信息并且保存最近一次心跳应答信息。再具体看看ResourceTracker#nodeHeart方法:

public NodeHeartbeatResponse nodeHeartbeat(NodeHeartbeatRequest request)
throws YarnException, IOException {
//从RPC Clinet中获得nodeManager所在节点的健康状况
NodeStatus remoteNodeStatus = request.getNodeStatus();
/**
* Here is the node heartbeat sequence...
* 1. Check if it's a registered node
* 2. Check if it's a valid (i.e. not excluded) node
* 3. Check if it's a 'fresh' heartbeat i.e. not duplicate heartbeat
* 4. Send healthStatus to RMNode
*/ NodeId nodeId = remoteNodeStatus.getNodeId(); // 1. Check if it's a registered node
RMNode rmNode = this.rmContext.getRMNodes().get(nodeId);
if (rmNode == null) {
/* node does not exist */
String message = "Node not found resyncing " + remoteNodeStatus.getNodeId();
LOG.info(message);
resync.setDiagnosticsMessage(message);
return resync;
} // Send ping
this.nmLivelinessMonitor.receivedPing(nodeId); // 2. Check if it's a valid (i.e. not excluded) node
if (!this.nodesListManager.isValidNode(rmNode.getHostName())) {
String message =
"Disallowed NodeManager nodeId: " + nodeId + " hostname: "
+ rmNode.getNodeAddress();
LOG.info(message);
shutDown.setDiagnosticsMessage(message);
this.rmContext.getDispatcher().getEventHandler().handle(
new RMNodeEvent(nodeId, RMNodeEventType.DECOMMISSION));
return shutDown;
} // 3. Check if it's a 'fresh' heartbeat i.e. not duplicate heartbeat
NodeHeartbeatResponse lastNodeHeartbeatResponse = rmNode.getLastNodeHeartBeatResponse();
if (remoteNodeStatus.getResponseId() + == lastNodeHeartbeatResponse
.getResponseId()) {
LOG.info("Received duplicate heartbeat from node "
+ rmNode.getNodeAddress());
return lastNodeHeartbeatResponse;
} else if (remoteNodeStatus.getResponseId() + < lastNodeHeartbeatResponse
.getResponseId()) {
String message =
"Too far behind rm response id:"
+ lastNodeHeartbeatResponse.getResponseId() + " nm response id:"
+ remoteNodeStatus.getResponseId();
LOG.info(message);
resync.setDiagnosticsMessage(message);
// TODO: Just sending reboot is not enough. Think more.
this.rmContext.getDispatcher().getEventHandler().handle(
new RMNodeEvent(nodeId, RMNodeEventType.REBOOTING));
return resync;
} // Heartbeat response
NodeHeartbeatResponse nodeHeartBeatResponse = YarnServerBuilderUtils
.newNodeHeartbeatResponse(lastNodeHeartbeatResponse.
getResponseId() + , NodeAction.NORMAL, null, null, null, null,
nextHeartBeatInterval);
rmNode.updateNodeHeartbeatResponseForCleanup(nodeHeartBeatResponse); populateKeys(request, nodeHeartBeatResponse); // 4. Send status to RMNode, saving the latest response.
this.rmContext.getDispatcher().getEventHandler().handle(
new RMNodeStatusEvent(nodeId, remoteNodeStatus.getNodeHealthStatus(),
remoteNodeStatus.getContainersStatuses(),
remoteNodeStatus.getKeepAliveApplications(), nodeHeartBeatResponse)); return nodeHeartBeatResponse;
}

(2)NodeListManager

NodeListManager主要分管黑名单(include列表)和白名单(exlude列表)管理功能,分别有yarnresouecemanager.nodes.include-path和yarnresourcemanager.nodes.exclude-path指定。黑名单列表中的nodes不能够和RM直接通信(直接抛出RPC异常),管理员可以对这两个列表进行编辑,然后使用$HADOOP_HOME/bin/yarn rmadmin -refreshNodes动态加载修改后的列表,使之生效。

(3)NMLivelinessMonitor

NMLivelinessMonitor主要是分管心跳异常请求。该服务会周期性地遍历集群中的所有NodeManager,如果某个NodeManager在一定时间内(默认10min,可以有参数yarn.nm.liveness-monitor.expiry-interval-ms配置)没有进行心跳汇报,那么则认为它已经死掉,同时在该节点上运行的Container也会被置为运行失败释放资源。那么这些被置为失败的Container是不会直接被RM分配执行的,RM只是负责将这些被置为失败的Container信息告诉它们所对应的ApplicationMaster,需不需要重新运行它说的算,如果需要重新运行的话,该ApplicationMaster要重新向RM申请资源,然后由ApplicationMaster与对应的NodeManager通信以重新运行之前失败的Container。

2、ApplicationMaster管理模块

ApplicationMaster的管理主要是用ResouceManager内部的3个组件来完成:ApplicationMasterLauncher、AMLivelinessMonitor、ApplicationMasterService。

(1)先说说ApplicationMaster和ResourceManager整个的交互流程:

步骤一:

当ResourceManager接收到客户端提交应用程序请求时就会立马向资源管理器申请一个资源用于启动该应用程序所对应的ApplicationMaster,申请到资源后由ApplicationMasterLaucher与对应的NodeManager进行通信,要求该NodemManager在其所在节点启动该ApplicationMaster。

步骤二:

ApplicationMaster启动完毕后,ApplicationMasterLuacher通过事件的形式将刚刚启动的ApplicationMaster注册到AMLivelinessMonitor,以启动心跳监控。

步骤三:

ApplicationMaster启动后主动向ApplicationMasterService注册,并将自己所在host、端口等信息向其汇报。

步骤四:

ApplicationMaster在运行的过程中不断向ApplicationMasterService发送心跳。

步骤五:

ApplicationMasterService每次收到ApplicationMaster的心跳信息后,会同时AMLivelinessMonitor更新其最近一次发送心跳的时间。

步骤六:

当应用程序运行完毕后,ApplicationMaster向ApplicationMasterService请求注销自己。

步骤七:

ApplicationMasterService收到注销请求后,会将该应用程序的运行状态标注为完成,并且同时AMLivelinessMonitor移除对该ApplicationMaster的心跳监控。

(2)内置管理组件的详细说明

这里展开说说这3个组件的一些运行机理。

  • ApplicationMasterLaucher

ApplicationMasterLaucher是以线程池方式实现的一个事件处理器,其主要处理AMLaucherEvent类型的事件,包括启动(LAUNCH)和清除(CLEANUP)一个ApplicationMaster的事件。

当接收到LAUNCH类型的事件,ApplicationMasterLaucher立马会和对应的NodeManager进行通信,并且带上启动该ApplicationMaster所需要的各种信息,包括:启动命令、JAR包、环境变量等信息。NodeManager接收到来自ApplicationMasterLaucher的启动命令就会启动ApplicationMaster。

当接收到CLEANUP类型事件,ApplicationMasterLaucher立马会和对应的NodeManager进行通信,要求NodeManager杀死该ApplicationMaster,并释放掉资源。

  • AMLivelinessMonitor

AMLivelinessMonitor的功能和NMLivelinessMonitor的功能几乎一样,只不过AMLivelinessMonitor监控的是ApplicationMaster,而NMLivelinessMonitor监控的是NodeManager。

AMLivelinessMonitor会周期性地遍历集群中的所有ApplicationMaster,如果某个ApplicationMaster在一定时间内(默认10min,可以有参数yarn.am.liveness-monitor.expiry-interval-ms配置)没有进行心跳汇报,那么则认为它已经死掉,同时该ApplicationMaster关联运行的Container也会被置为运行失败释放资源。如果Application运行失败,则有ResourceManager重新为它申请资源,并且在另外的节点上启动它(AM启动尝试次数由参数yarn.resourcemanager.am.max-attempts控制,默认2)。那么这些被置为失败的Container是不会直接被RM分配执行的,RM只是负责将这些被置为失败的Container信息告诉它们所对应的ApplicationMaster,需不需要重新运行它说的算,如果需要从新运行的话,该ApplicationMaster要从新向RM申请资源,然后由ApplicationMaster与对应的NodeManager通信以从新运行之前失败的Container。

  • ApplicationMasterService

ApplicationMasterService的主要职能是处理来自ApplicationMaster的心跳请求,另外也还处理Application的注册和清理请求。注册是Application启动完成后发生的,它向ApplicationMasterService发送注册请求包,包含:ApplicationMaster所在的节点、RPC端口、tracking url等信息。

处理心跳信息是周期型行为,只要ApplicationMaster还在运行此类请求都会发生。ApplicationMaster向ApplicationMasterService发送的心跳请求包,包含信息:请求资源类型的描述、待释放的container列表等。ApplicationMasterService返回的心跳应答信息包含:ApplicationMasterService为之分配的Container、失败的Container等信息。

清理请求是在ApplicationMaster运行完毕后,向ApplicationMasterService发送的,主要是叫其回收释放资源。

Yarn之ResourceManager详细分析的更多相关文章

  1. YARN DistributedShell源码分析与修改

    YARN DistributedShell源码分析与修改 YARN版本:2.6.0 转载请注明出处:http://www.cnblogs.com/BYRans/ 1 概述 2 YARN Distrib ...

  2. YARN中的失败分析

    YARN中的失败分析 对于在YARN中运行的MapReduce程序,需要考虑以下几种实体的失败任务.application master.节点管理器.资源管理器 1. 任务运行失败 任务运行失败类似于 ...

  3. ZIP压缩算法详细分析及解压实例解释

    最近自己实现了一个ZIP压缩数据的解压程序,觉得有必要把ZIP压缩格式进行一下详细总结,数据压缩是一门通信原理和计算机科学都会涉及到的学科,在通信原理中,一般称为信源编码,在计算机科学里,一般称为数据 ...

  4. 1125MySQL Sending data导致查询很慢的问题详细分析

    -- 问题1 tablename使用主键索引反而比idx_ref_id慢的原因EXPLAIN SELECT SQL_NO_CACHE COUNT(id) FROM dbname.tbname FORC ...

  5. LinkedList详细分析

    一.源码解析1. LinkedList类定义2.LinkedList数据结构原理3.私有属性4.构造方法5.元素添加add()及原理6.删除数据remove()7.数据获取get()8.数据复制clo ...

  6. android ListView 九大重要属性详细分析、

    android ListView 九大重要属性详细分析. 1.android ListView 一些重要属性详解,兄弟朋友可以参考一下. 首先是stackFromBottom属性,这只该属性之后你做好 ...

  7. C语言中的static 详细分析

    转自:http://blog.csdn.net/keyeagle/article/details/6708077/ google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇大 ...

  8. Linux内核OOM机制的详细分析(转)

    Linux 内核 有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了 防止内存耗尽而内核会把该进程杀掉.典 ...

  9. Android-Native-Server 启动和注册详细分析

    Android-Native-Server 启动和注册详细分析     以mediaService为实例来讲解: mediaService的启动入口 是一个 传统的  main()函数 源码位置E:\ ...

随机推荐

  1. 处理unsigned相减错误(BIGINT UNSIGNED value is out of range)

    mysql 当两个字段想减时,如果其中一个或两个字段的类型的unsigned无签名类型,如果想减的值小于0则会报错(BIGINT UNSIGNED value is out of range) 测试: ...

  2. HQL的执行过程

    解释器.编译器.优化器完成HQL查询语句从词法分析.语法分析.编译.优化以及查询计划(Plan)的生成.生成的查询计划存储在HDFS中,并在随后有mapreduce调用执行. 举个例子: 第一步:输入 ...

  3. linux的setup命令设置网卡和防火墙等

    以前在centos上配置网卡都是纯命令行,今天发现linux原来还有一个setup那么好用的命令,真是相见恨晚,以后防火墙.网卡.其他网络配置.系统配置(开机启动项)都可用他来完成了

  4. Python-Numpy的tile函数用法

    1.函数的定义与说明 函数格式tile(A,reps) A和reps都是array_like A的类型众多,几乎所有类型都可以:array, list, tuple, dict, matrix以及基本 ...

  5. LeetCode——Move Zeroes

    Description: Given an array nums, write a function to move all 0's to the end of it while maintainin ...

  6. LeetCode - Employees Earning More Than Their Managers

    Description: The Employee table holds all employees including their managers. Every employee has an ...

  7. TweenLite简单运用

    参考:TweenLite说明 1 ease TweenLite.to(nextLevelTip, 1.5, { x:0, ease:Bounce.easeOut } ); 2 delayCall 语法 ...

  8. 微信小程序 --- 获取设备信息

    获取设备信息: wx.getSystemInfo model:手机型号 pixelRatio:设备像素比 windowWidth:窗口宽度 windowHeight:窗口高度 language:语言 ...

  9. 次小生成树(poj1679)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20737   Accepted: 7281 D ...

  10. 新版jquery的ajax调用 , jquery1.5以上

    原文出处:http://api.jquery.com/jQuery.ajax/,该链接页面底部有代码展示 示例1: $.ajax({ method: "POST", url: &q ...