Samza在YARN上的启动过程 =》 之二 submitApplication
首先,来看怎么构造一个org.apache.hadoop.yarn.client.api.YarnClient
class ClientHelper(conf: Configuration) extends Logging {
val yarnClient = YarnClient.createYarnClient
info("trying to connect to RM %s" format conf.get(YarnConfiguration.RM_ADDRESS, YarnConfiguration.DEFAULT_RM_ADDRESS))
yarnClient.init(conf);
yarnClient.start
!!!这个client还有个start方法,看来它跟RM很谈得来。的确,它实现了service这个接口。 好吧,它是一个服务。在YarnJobFactory中,我们用yarn-site.xml构造了一个YarnConfiguration对象,现在用它来初始化YarnClient,因为我们至少需要RM在哪,对不?
下边分几部分看submitApplication方法的实现
第一次调用YarnClient - 获取信息
def submitApplication(packagePath: Path, memoryMb: Int, cpuCore: Int, cmds: List[String], env: Option[Map[String, String]], name: Option[String]): Option[ApplicationId] = {
val app = yarnClient.createApplication
val newAppResponse = app.getNewApplicationResponse
var mem = memoryMb
var cpu = cpuCore
// If we are asking for memory more than the max allowed, shout out
if (mem > newAppResponse.getMaximumResourceCapability().getMemory()) {
throw new SamzaException("You're asking for more memory (%s) than is allowed by YARN: %s" format
(mem, newAppResponse.getMaximumResourceCapability().getMemory()))
}
// If we are asking for cpu more than the max allowed, shout out
if (cpu > newAppResponse.getMaximumResourceCapability().getVirtualCores()) {
throw new SamzaException("You're asking for more CPU (%s) than is allowed by YARN: %s" format
(cpu, newAppResponse.getMaximumResourceCapability().getVirtualCores()))
}
appId = Some(newAppResponse.getApplicationId)
首先通过yarnClient的createApplication方法获取一个YarnClientApplication对象。这是对RM的第一次请求,那么这次请求能得到什么信息呢?
通过这次请求得到的YarnClientApplication对象有两个方法:
- getApplicationSubmissionContext() , 它返回一个 ApplicationSubmissionContext对象。“
ApplicationSubmissionContextrepresents all of the information needed by theResourceManagerto launch theApplicationMasterfor an application.” - getNewApplicationResponse(), 它返回一个GetNewApplicationResponse对象。
鉴于YarnClient的createApplication方法没有任何参数,而YarnClient本身的状态中由用户指定的部分只是YarnConfiguration的内容,因此这个createApplication方法并不会告诉YARN客户端对资源的需求,因此它返回的app对象只包含了yarn的RM本身的信息。
在获取了app这个对象之后,submitApplication方法通过
val newAppResponse = app.getNewApplicationResponse
从中取出了newAppResponse这个对象,然后从中取出了当前YARN集群最多支持的内存和CPU数目(TODO:这个值是当前可用的资源的值,还是整体上最大资源值)。然后对比给AM申请的container想要的内存和CPU,如果超出了YARN支持的最大值,就抛出异常。
否则,就把从newAppResponse中获取的applicationId赋给appId。看来在第一次请求时,YARN就给分配了appId,只是这个appId,并不和资源关联。
第二调用YarnClient - 提交job
如果资源足够,AM就可以提交,那就开始填写AM运行需要的资源,具体来说就是组装ApplicationSubmissionContext类的一个对象
name match {
case Some(name) => { appCtx.setApplicationName(name) }
case None => { appCtx.setApplicationName(appId.toString) }
}
env match {
case Some(env) => {
containerCtx.setEnvironment(env)
info("set environment variables to %s for %s" format (env, appId.get))
}
case None => None
}
// set the local package so that the containers and app master are provisioned with it
val packageUrl = ConverterUtils.getYarnUrlFromPath(packagePath)
val fileStatus = packagePath.getFileSystem(conf).getFileStatus(packagePath)
packageResource.setResource(packageUrl)
info("set package url to %s for %s" format (packageUrl, appId.get))
packageResource.setSize(fileStatus.getLen)
info("set package size to %s for %s" format (fileStatus.getLen, appId.get))
packageResource.setTimestamp(fileStatus.getModificationTime)
packageResource.setType(LocalResourceType.ARCHIVE)
packageResource.setVisibility(LocalResourceVisibility.APPLICATION)
resource.setMemory(mem)
info("set memory request to %s for %s" format (mem, appId.get))
resource.setVirtualCores(cpu)
info("set cpu core request to %s for %s" format (cpu, appId.get))
appCtx.setResource(resource)
containerCtx.setCommands(cmds.toList)
info("set command to %s for %s" format (cmds, appId.get))
containerCtx.setLocalResources(Collections.singletonMap("__package", packageResource))
appCtx.setApplicationId(appId.get)
info("set app ID to %s" format appId.get)
appCtx.setAMContainerSpec(containerCtx)
appCtx.setApplicationType(ClientHelper.applicationType)
info("submitting application request for %s" format appId.get)
yarnClient.submitApplication(appCtx)
这段代码设置了一个ApplicationSubmissionContext对象,然后再用yarnClient把它提交。这样就提交了一个YARN job。
这样YarnClient一共用了两次,初始一次请求,获取appID和YARN的资源上限的情况,第二次请求,真正提交job。
这段代码让我有些疑惑。首先appCtx大致分为两部分,一部分是job的信息,比如application type和application ID,另一部分和AM有关。和AM有关的部分又可以分成两块: 1. cpu和内存的大小,这两个资源组装在Resource这个类的对象里,由setResource设置到 appCtx中 2:运行container所需的命令和文件、环量变量,这部分设置在一个ContainerLaunchContext对象中,然后这个对象再被调置在appCtx中。疑惑的地方在于:为什么AM所需的资源要分成两部分呢?cpu和内存本就该是container申请的一部分呀?
看看API里关于containerLaunchContext类的说明,就更不明白了
ContainerLaunchContextrepresents all of the information needed by theNodeManagerto launch a container.It includes details such as:
ContainerIdof the container.Resourceallocated to the container.- User to whom the container is allocated.
- Security tokens (if security is enabled).
LocalResourcenecessary for running the container such as binaries, jar, shared-objects, side-files etc.- Optional, application-specific binary service data.
- Environment variables for the launched process.
- Command to launch the container.
好吧,“Resource allocated to the container.”, 这一条ContainerLanchContext并没有体现,在它提供的方法中并不能设置Resource。这不是骗人吗?
而appCtx却有单独的一个setAMContainerSpec 方法来设置Resource。那么在申请运行task所需的container时,如果说明其所需的资源呢?看来一定不是用了这个ContainerLaunchContext对象。
两个不同的协议
Samza AM为task申请container的代码在SamzaAppMasterTaskManager这个类里
protected def requestContainers(memMb: Int, cpuCores: Int, containers: Int) {
info("Requesting %d container(s) with %dmb of memory" format (containers, memMb))
val capability = Records.newRecord(classOf[Resource])
val priority = Records.newRecord(classOf[Priority])
priority.setPriority(0)
capability.setMemory(memMb)
capability.setVirtualCores(cpuCores)
(0 until containers).foreach(idx => amClient.addContainerRequest(new ContainerRequest(capability, null, null, priority)))
}
这里的amClient就是org.apache.hadoop.yarn.client.api.async.AMRMClientAsync类的对象。它用来和RM联系,处理container相关的事情。当AM请求container时,它就不用submitApplication中为AM设置container资源所需的那套动作了,而是使用ContainerRequest这类。而且ContainerRequest的构造方法中
public ContainerRequest(Resource capability, String[] nodes, String[] racks, Priority priority, boolean relaxLocality)
使用了Resource做为参数。
可见为AM申请container和为task申请container走的过程的确不一样。毕竟,为AM的运行申请container是作为提交任务的一部分。最终发现两个是使用的不同的协议。提交任务时,使用的是这个协议:
message ApplicationSubmissionContextProto {
optional ApplicationIdProto application_id = 1;
optional string application_name = 2 [default = "N/A"];
optional string queue = 3 [default = "default"];
optional PriorityProto priority = 4;
optional ContainerLaunchContextProto am_container_spec = 5;
optional bool cancel_tokens_when_complete = 6 [default = true];
optional bool unmanaged_am = 7 [default = false];
optional int32 maxAppAttempts = 8 [default = 0];
optional ResourceProto resource = 9;
optional string applicationType = 10 [default = "YARN"];
}
message ContainerLaunchContextProto {
repeated StringLocalResourceMapProto localResources = 1;
optional bytes tokens = 2;
repeated StringBytesMapProto service_data = 3;
repeated StringStringMapProto environment = 4;
repeated string command = 5;
repeated ApplicationACLMapProto application_ACLs = 6;
}
ContainerLaunchContextProto里根本没有代表cpu和内存资源的ResourceProto,这个Protocol是在ApplicationSubmissionContextProto里。对照containerLaunchContext类的说明,的确显得很奇怪。
而申请container的请求,走的是
message ResourceRequestProto {
optional PriorityProto priority = 1;
optional string resource_name = 2;
optional ResourceProto capability = 3;
optional int32 num_containers = 4;
optional bool relax_locality = 5 [default = true];
}
message ResourceProto {
optional int32 memory = 1;
optional int32 virtual_cores = 2;
}
Samza在YARN上的启动过程 =》 之二 submitApplication的更多相关文章
- Samza在YARN上的启动过程 =》 之一
运行脚本,提交job 往YARN提交Samza job要使用run-job.sh这个脚本. samza-example/target/bin/run-job.sh --config-factory= ...
- Linux运维面试题:请简要说明Linux系统在目标板上的启动过程?
Linux运维面试题:请简要说明Linux系统在目标板上的启动过程? 该问题是Linux运维面试最常见的问题之一,问题答案如下: 1.用户打开PC的电源,BIOS开机自检,按BIOS中设置的启动设备( ...
- Spring Boot启动过程(二)
书接上篇 该说refreshContext(context)了,首先是判断context是否是AbstractApplicationContext派生类的实例,之后调用了强转为AbstractAppl ...
- Android应用程序启动过程(二)分析
本文依据Android6.0源码,从点击Launcher图标,直至解析到MainActivity#OnCreate()被调用. Launcher简析 Launcher也是个应用程序,不过是个特殊的应用 ...
- Tomcat启动过程(二):EndPoint解析
EndPoint提供基础的网络IO服务,用来实现网络连接和控制,它是服务器对外I/O操作的接入点.主要任务是管理对外的socket连接,同时将建立好的socket连接交到合适的工作线程中去.里面两个主 ...
- Spring Boot启动过程(四):Spring Boot内嵌Tomcat启动
之前在Spring Boot启动过程(二)提到过createEmbeddedServletContainer创建了内嵌的Servlet容器,我用的是默认的Tomcat. private void cr ...
- Spring Boot启动过程(七):Connector初始化
Connector实例的创建已经在Spring Boot启动过程(四):Spring Boot内嵌Tomcat启动中提到了: Connector是LifecycleMBeanBase的子类,先是设置L ...
- Spring Boot启动过程(三)
我已经很精简了,两篇(Spring Boot启动过程(一).pring Boot启动过程(二))依然没写完,接着来. refreshContext之后的方法是afterRefresh,这名字起的真.. ...
- Hadoop 系列文章(三) 配置部署启动YARN及在YARN上运行MapReduce程序
这篇文章里我们将用配置 YARN,在 YARN 上运行 MapReduce. 1.修改 yarn-env.sh 环境变量里的 JAVA_HOME 路径 [bamboo@hadoop-senior ha ...
随机推荐
- Span flag详解
在android中,如果要实现text的各种样式,图文混排等,简单的样式可以靠几个不同的textview来拼成,而复杂的样式要求,用不同的textview来拼接则不太现 实.这时候就spannable ...
- jQuery 日历控件 FullCalendar 初识
最近有个日程管理的需求,就学习了一下 FullCalendar 控件的一些基本知识,本文不是详细介绍该控件的 API 的文档,而是记录本人使用过程中的一些学习情况. 先看一下效果图 月/周/日视图 ...
- UVALive 3027(并查集)
题意:某公司的各企业群要建立联系,I i j 表示企业i与企业j建立联系,并且以企业j为中心(并查集中的父亲)(企业j为暂时的中心企业),E i 表示查询企业 i 距离此时的中心企业的距离.各企业间的 ...
- Windows服务器nginx+tomcat服务负载均衡
一.安装两个tomcat服务自启动 1. 解压两个tomcat,名称为分别1,2 2. 配置环境变量 3. 修改文件server.xml中的三个端口号,使得两个tomcat不冲突 (1)<Ser ...
- C语言中格式化输出的转换说明的fldwidth和precision解析
首先说什么是C语言的格式化输出,就是printf和它的几个变种(grep -E "v?(sn|s|f)printf").像这些函数都有一个参数format,format中可以加点转 ...
- 【Winform】 无法将类型为“System.Windows.Forms.SplitContainer”的对象强制转换为类型“System.ComponentModel.ISupportInitialize”。
问题:将dotnet framework 4.0 切换到2.0时,编译没有问题,在运行时出现如下错误:System.InvalidCastException: 无法将类型为“System.Window ...
- 几个好用的截取字符串的php函数分享
分享几个好用的PHP 截取字符串函数(支持gb2312和utf-8). 1.截取GB2312字符用的函数 <?php /** **截取中文字符串 * edit by www.jbxue.com ...
- 思道OA PK 通达OA 同场竞技 谁与争锋
技术架构 思道OA 通达OA 开发语言 微软ASP.NET 4.0 PHP开源脚本语言 64位平台 64位 32位 数据库 SQL Server大数据库 MySQL开源数据库 官网下载 下载地址 下载 ...
- ajax中的post方法中回调函数不执行的问题
前一段时间接触了JQuery Ajax中的.post()方法和.get()方法,感觉到ajax的简洁和强大,当用到.post()方法时,去W3上查找相关的使用方法,感觉十分简单,用法很明了,然后,直接 ...
- [Learn Android Studio 汉化教程]第四章 : Refactoring Code
[Learn Android Studio 汉化教程]第四章 : Refactoring Code 第四章 Refactoring Code 重构代码 在Android Studio中开发,解决 ...