YARN是hadoop系统上的资源统一管理平台,其主要作用是实现集群资源的统一管理和调度(目前还不完善,只支持粗粒度的CPU和内存的的调配);

它的基本思想是将Mapreduce的jobtracker拆分成两个独立的服务:一个全局的资源管理器ResourceManager和每个应用程序特有的ApplicationMaster。其中ResourceManager负责整个系统资源的管理和分配,而ApplicationMaster则负责单个应用程序的管理;

YARN上的应用按其运行的生命周期的长短分为长应用和短应用。

  1.短应用通常是分析作业,作业从提交到完成,所耗时间是有限的,作业完成后,其占用的资源就会被释放,归还给YARN再次分配

  2.长应用通常是一些服务,启动后除非意外或人为终止,将一直运行下去。长应用通常长期占用集群上的一些资源,且运行期间对资源的需求也时常变化。

YARN在2.2.0版本以后增强了对长应用的支持。


用户向YARN提交一个应用程序后,YARN将分为两个阶段运行改应用程序:第一个阶段是启动ApplicationMaster;第二个阶段是由ApplicationMaster创建应用程序,为它申请资源,并监控它的整个运行过程,直到运行成功。

YARN的工作流程可以分为以下几个步骤:

  1.用户向YARN提交应用程序,其中包括ApplicationMaster程序、启动ApplicationMaster的命令、用户程序等;

  2.ResourceManager为该应用程序分配第一个Container,并与对应的NodeManager通信,要求它在整个Container中启动应用程序的ApplicationMaster;

  3ApplicationMaster首先向ResourceManager注册,这样用户可以直接通过ResourceManager查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它的运行状态,直到运行结束,即重复步骤4~7;

  4.ApplicationMaster采用轮询的方式通过RPC协议向ResourceManager申请和领取资源;

  5.一旦ApplicationMaster申请到资源后,则与对应的NodeManager通信,要求其启动任务;

  6.NodeManager为任务设置好运行环境(包括环境变量、jar包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务;

  7.各个任务通过某RPC协议向ApplicationMaster汇报自己的状态和进度,以让ApplicationMaster随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。

    在应用程序运行过程中,用户可以随时通过RPC向ApplicationMaster查询应用程序的当前运行状态;

  8.应用程序运行完成后,ApplicationMaster向ResourceManager注销并关闭自己。


在单机程序设计中,为了快速处理一个大的数据集,通常采用多线程并行编程,大体流程如下:先有操作系统启动一个主线程,由它负责数据气氛、任务分配、子线程启动和销毁等工作,而各个子线程只负责计算自己的数据,当所有子线程处理完数据后,主线程再退出;

类比理解,YARN上的应用程序运行过程与之非常相近,只不过它是集群上的分布式并行编程。可以将YARN看做一个云操作系统,它负责为应用程序启动ApplicationMaster(相当于主线程),然后再由ApplicationMaster负责数据气氛、任务分配、启动和监控等工作,而由ApplicationMaster启动其他各个Node的Task(相当于子线程)仅负责计算任务,当所有任务计算完成后,ApplicationMaster认为应用程序运行完成,然后退出。


YARN上协议层面的通信动作

上图涉及三个RPC协议:

  • ApplicationClientProtocol: Client-RM之间的协议,主要用于应用的提交;

  • ApplicationMasterProtocol: AM-RM之间的协议,AM通过该协议向RM注册并申请资源;

  • ContainerManagementProtocol: AM-NM之间的协议,AM通过该协议控制NM启动容器。


YARN上程序层面的调用动作

可以看出,客户端的主要作用就是应用的提交和监控应用运行。


程序跟踪

http://www.cnblogs.com/admln/p/hadoop2-work-excute-submit.html 的

JobSubmitter.java
status = submitClient.submitJob( jobId, submitJobDir.toString(), job.getCredentials());

接起

   @Override
public JobStatus submitJob(JobID jobId, String jobSubmitDir, Credentials ts)
throws IOException, InterruptedException { addHistoryToken(ts); // Construct necessary information to start the MR AM
ApplicationSubmissionContext appContext =
createApplicationSubmissionContext(conf, jobSubmitDir, ts); // Submit to ResourceManager
try {
ApplicationId applicationId =
resMgrDelegate.submitApplication(appContext); ApplicationReport appMaster = resMgrDelegate
.getApplicationReport(applicationId);
String diagnostics =
(appMaster == null ?
"application report is null" : appMaster.getDiagnostics());
if (appMaster == null
|| appMaster.getYarnApplicationState() == YarnApplicationState.FAILED
|| appMaster.getYarnApplicationState() == YarnApplicationState.KILLED) {
throw new IOException("Failed to run job : " +
diagnostics);
}
return clientCache.getClient(jobId).getJobStatus(jobId);
} catch (YarnException e) {
throw new IOException(e);
}
}

其中最重要的语句之一就是

ApplicationSubmissionContext appContext =
createApplicationSubmissionContext(conf, jobSubmitDir, ts);

读注释可知它用于启动AppMaster前构造必要的信息

   public ApplicationSubmissionContext createApplicationSubmissionContext(
Configuration jobConf,
String jobSubmitDir, Credentials ts) throws IOException {
ApplicationId applicationId = resMgrDelegate.getApplicationId(); // Setup resource requirements
Resource capability = recordFactory.newRecordInstance(Resource.class);
capability.setMemory(
conf.getInt(
MRJobConfig.MR_AM_VMEM_MB, MRJobConfig.DEFAULT_MR_AM_VMEM_MB
)
);
capability.setVirtualCores(
conf.getInt(
MRJobConfig.MR_AM_CPU_VCORES, MRJobConfig.DEFAULT_MR_AM_CPU_VCORES
)
);
LOG.debug("AppMaster capability = " + capability); // Setup LocalResources
Map<String, LocalResource> localResources =
new HashMap<String, LocalResource>(); Path jobConfPath = new Path(jobSubmitDir, MRJobConfig.JOB_CONF_FILE); URL yarnUrlForJobSubmitDir = ConverterUtils
.getYarnUrlFromPath(defaultFileContext.getDefaultFileSystem()
.resolvePath(
defaultFileContext.makeQualified(new Path(jobSubmitDir))));
LOG.debug("Creating setup context, jobSubmitDir url is "
+ yarnUrlForJobSubmitDir); localResources.put(MRJobConfig.JOB_CONF_FILE,
createApplicationResource(defaultFileContext,
jobConfPath, LocalResourceType.FILE));
if (jobConf.get(MRJobConfig.JAR) != null) {
Path jobJarPath = new Path(jobConf.get(MRJobConfig.JAR));
LocalResource rc = createApplicationResource(defaultFileContext,
jobJarPath,
LocalResourceType.PATTERN);
String pattern = conf.getPattern(JobContext.JAR_UNPACK_PATTERN,
JobConf.UNPACK_JAR_PATTERN_DEFAULT).pattern();
rc.setPattern(pattern);
localResources.put(MRJobConfig.JOB_JAR, rc);
} else {
// Job jar may be null. For e.g, for pipes, the job jar is the hadoop
// mapreduce jar itself which is already on the classpath.
LOG.info("Job jar is not present. "
+ "Not adding any jar to the list of resources.");
} // TODO gross hack
for (String s : new String[] {
MRJobConfig.JOB_SPLIT,
MRJobConfig.JOB_SPLIT_METAINFO }) {
localResources.put(
MRJobConfig.JOB_SUBMIT_DIR + "/" + s,
createApplicationResource(defaultFileContext,
new Path(jobSubmitDir, s), LocalResourceType.FILE));
} // Setup security tokens
DataOutputBuffer dob = new DataOutputBuffer();
ts.writeTokenStorageToStream(dob);
ByteBuffer securityTokens = ByteBuffer.wrap(dob.getData(), 0, dob.getLength()); // Setup the command to run the AM
List<String> vargs = new ArrayList<String>(8);
vargs.add(Environment.JAVA_HOME.$() + "/bin/java"); // TODO: why do we use 'conf' some places and 'jobConf' others?
long logSize = TaskLog.getTaskLogLength(new JobConf(conf));
String logLevel = jobConf.get(
MRJobConfig.MR_AM_LOG_LEVEL, MRJobConfig.DEFAULT_MR_AM_LOG_LEVEL);
MRApps.addLog4jSystemProperties(logLevel, logSize, vargs); // Check for Java Lib Path usage in MAP and REDUCE configs
warnForJavaLibPath(conf.get(MRJobConfig.MAP_JAVA_OPTS,""), "map",
MRJobConfig.MAP_JAVA_OPTS, MRJobConfig.MAP_ENV);
warnForJavaLibPath(conf.get(MRJobConfig.MAPRED_MAP_ADMIN_JAVA_OPTS,""), "map",
MRJobConfig.MAPRED_MAP_ADMIN_JAVA_OPTS, MRJobConfig.MAPRED_ADMIN_USER_ENV);
warnForJavaLibPath(conf.get(MRJobConfig.REDUCE_JAVA_OPTS,""), "reduce",
MRJobConfig.REDUCE_JAVA_OPTS, MRJobConfig.REDUCE_ENV);
warnForJavaLibPath(conf.get(MRJobConfig.MAPRED_REDUCE_ADMIN_JAVA_OPTS,""), "reduce",
MRJobConfig.MAPRED_REDUCE_ADMIN_JAVA_OPTS, MRJobConfig.MAPRED_ADMIN_USER_ENV); // Add AM admin command opts before user command opts
// so that it can be overridden by user
String mrAppMasterAdminOptions = conf.get(MRJobConfig.MR_AM_ADMIN_COMMAND_OPTS,
MRJobConfig.DEFAULT_MR_AM_ADMIN_COMMAND_OPTS);
warnForJavaLibPath(mrAppMasterAdminOptions, "app master",
MRJobConfig.MR_AM_ADMIN_COMMAND_OPTS, MRJobConfig.MR_AM_ADMIN_USER_ENV);
vargs.add(mrAppMasterAdminOptions); // Add AM user command opts
String mrAppMasterUserOptions = conf.get(MRJobConfig.MR_AM_COMMAND_OPTS,
MRJobConfig.DEFAULT_MR_AM_COMMAND_OPTS);
warnForJavaLibPath(mrAppMasterUserOptions, "app master",
MRJobConfig.MR_AM_COMMAND_OPTS, MRJobConfig.MR_AM_ENV);
vargs.add(mrAppMasterUserOptions); vargs.add(MRJobConfig.APPLICATION_MASTER_CLASS);
vargs.add("1>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR +
Path.SEPARATOR + ApplicationConstants.STDOUT);
vargs.add("2>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR +
Path.SEPARATOR + ApplicationConstants.STDERR); Vector<String> vargsFinal = new Vector<String>(8);
// Final command
StringBuilder mergedCommand = new StringBuilder();
for (CharSequence str : vargs) {
mergedCommand.append(str).append(" ");
}
vargsFinal.add(mergedCommand.toString()); LOG.debug("Command to launch container for ApplicationMaster is : "
+ mergedCommand); // Setup the CLASSPATH in environment
// i.e. add { Hadoop jars, job jar, CWD } to classpath.
Map<String, String> environment = new HashMap<String, String>();
MRApps.setClasspath(environment, conf); // Setup the environment variables for Admin first
MRApps.setEnvFromInputString(environment,
conf.get(MRJobConfig.MR_AM_ADMIN_USER_ENV));
// Setup the environment variables (LD_LIBRARY_PATH, etc)
MRApps.setEnvFromInputString(environment,
conf.get(MRJobConfig.MR_AM_ENV)); // Parse distributed cache
MRApps.setupDistributedCache(jobConf, localResources); Map<ApplicationAccessType, String> acls
= new HashMap<ApplicationAccessType, String>(2);
acls.put(ApplicationAccessType.VIEW_APP, jobConf.get(
MRJobConfig.JOB_ACL_VIEW_JOB, MRJobConfig.DEFAULT_JOB_ACL_VIEW_JOB));
acls.put(ApplicationAccessType.MODIFY_APP, jobConf.get(
MRJobConfig.JOB_ACL_MODIFY_JOB,
MRJobConfig.DEFAULT_JOB_ACL_MODIFY_JOB)); // Setup ContainerLaunchContext for AM container
ContainerLaunchContext amContainer =
ContainerLaunchContext.newInstance(localResources, environment,
vargsFinal, null, securityTokens, acls); // Set up the ApplicationSubmissionContext
ApplicationSubmissionContext appContext =
recordFactory.newRecordInstance(ApplicationSubmissionContext.class);
appContext.setApplicationId(applicationId); // ApplicationId
appContext.setQueue( // Queue name
jobConf.get(JobContext.QUEUE_NAME,
YarnConfiguration.DEFAULT_QUEUE_NAME));
appContext.setApplicationName( // Job name
jobConf.get(JobContext.JOB_NAME,
YarnConfiguration.DEFAULT_APPLICATION_NAME));
appContext.setCancelTokensWhenComplete(
conf.getBoolean(MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN, true));
appContext.setAMContainerSpec(amContainer); // AM Container
appContext.setMaxAppAttempts(
conf.getInt(MRJobConfig.MR_AM_MAX_ATTEMPTS,
MRJobConfig.DEFAULT_MR_AM_MAX_ATTEMPTS));
appContext.setResource(capability);
appContext.setApplicationType(MRJobConfig.MR_APPLICATION_TYPE);
return appContext;
}

其中

ApplicationId applicationId = resMgrDelegate.getApplicationId();

就对应上图中的第一步,向ResourceManager申请ID;
其中包括了内存、CPU的分配,资源(程序、配置等)路径的配置,启动AppMaster的命令,检查java环境等等;

这些就对应上图中的第二步,初始化AM的配置;

而submitJob()方法中最重要语句之二就是

ApplicationId applicationId =
resMgrDelegate.submitApplication(appContext);

它用于将AM提交到RM,对应于上图中的第三步;
submitApplication()方法是由YarnClientImpl.java实现的,即:

   @Override
public ApplicationId
submitApplication(ApplicationSubmissionContext appContext)
throws YarnException, IOException {
ApplicationId applicationId = appContext.getApplicationId();
appContext.setApplicationId(applicationId);
SubmitApplicationRequest request =
Records.newRecord(SubmitApplicationRequest.class);
request.setApplicationSubmissionContext(appContext);
rmClient.submitApplication(request); int pollCount = 0;
while (true) {
YarnApplicationState state =
getApplicationReport(applicationId).getYarnApplicationState();
if (!state.equals(YarnApplicationState.NEW) &&
!state.equals(YarnApplicationState.NEW_SAVING)) {
break;
}
// Notify the client through the log every 10 poll, in case the client
// is blocked here too long.
if (++pollCount % 10 == 0) {
LOG.info("Application submission is not finished, " +
"submitted application " + applicationId +
" is still in " + state);
}
try {
Thread.sleep(statePollIntervalMillis);
} catch (InterruptedException ie) {
}
} LOG.info("Submitted application " + applicationId + " to ResourceManager"
+ " at " + rmAddress);
return applicationId;
}

这个方法主要构造了一个请求,并将这个请求调用相关协议发出,即:

rmClient.submitApplication(request);

客户端类结构:


到这里客户端除了查询监控基本上没有什么动作了,之后就按照上面的协议通信图来进行了。

由于YARN的各种协议、接口、封装等,就简单从协议层面分析大概流程走向

(在查看协议代码的时候经常会看到google的字样,有点老祖宗的感觉)

客户端和RM之间的协议类是ApplicationClientProtocol

客户端和RM之间的通信动作包括:

1.获取应用ID

      public abstract void getNewApplication(
com.google.protobuf.RpcController controller,
org.apache.hadoop.yarn.proto.YarnServiceProtos.GetNewApplicationRequestProto request,
com.google.protobuf.RpcCallback<org.apache.hadoop.yarn.proto.YarnServiceProtos.GetNewApplicationResponseProto> done);

2.把应用提交到RM上

      public abstract void submitApplication(
com.google.protobuf.RpcController controller,
org.apache.hadoop.yarn.proto.YarnServiceProtos.SubmitApplicationRequestProto request,
com.google.protobuf.RpcCallback<org.apache.hadoop.yarn.proto.YarnServiceProtos.SubmitApplicationResponseProto> done);

具体步骤:

  1. 客户端通过getNewApplication方法从RM上获取应用ID;

  2. 客户端将应用相关的运行配置封装到ApplicationSubmissionContext中,通过submitApplication方法将应用提交到RM上;

  3. RM根据ApplicationSubmissionContext上封装的内容启动AM;

  4. 客户端通过AM或RM获取应用的运行状态,并控制应用的运行过程。

在获取应用程序ID后,客户端封装应用相关的配置到ApplicationSubmissionContext中,通过submitApplication方法提交到RM上。

ApplicationSubmissionContext主要包括如下几个部分:

  • applicationId: 通过getNewApplication获取的应用ID;

  • applicationName: 应用名称,将显示在YARN的web界面上;

  • applicationType: 应用类型,默认为”YARN”;

  • priority: 应用优先级,数值越小,优先级越高;

  • queue: 应用所属队列,不同应用可以属于不同的队列,使用不同的调度算法;

  • unmanagedAM: 布尔类型,表示AM是否由客户端启动(AM既可以运行在YARN平台之上,也可以运行在YARN平台之外。运行在YARN平台之上的AM通过RM启动,其运行所需的资源受YARN控制);

  • cancelTokensWhenComplete: 应用完成后,是否取消安全令牌;

  • maxAppAttempts: AM启动失败后,最大的尝试重启次数;

  • resource: 启动AM所需的资源(虚拟CPU数/内存),虚拟CPU核数是一个归一化的值;

  • amContainerSpec: 启动AM容器的上下文,主要包括如下内容:

  • tokens: AM所持有的安全令牌;

  • serviceData: 应用私有的数据,是一个Map,键为数据名,值为数据的二进制块;

  • environment: AM使用的环境变量;

  • commands: 启动AM的命令列表;

  • applicationACLs:应程序访问控制列表;

  • localResource: AM启动需要的本地资源列表,主要是一些外部文件、压缩包等。


之后就是RM创建AM,并执行某些动作了

AM的主要功能是按照业务需求,从RM处申请资源,并利用这些资源完成业务逻辑。因此,AM既需要与RM通信,又需要与NM通信。这里涉及两个协议,分别是AM-RM协议(ApplicationMasterProtocol)和AM-NM协议(ContainerManagementProtocol)

首先是AM-RM

AM-RM之间使用ApplicationMasterProtocol协议进行通信,该协议提供如下几个方法:

  //向RM注册AM    
  public abstract void registerApplicationMaster(
com.google.protobuf.RpcController controller,
org.apache.hadoop.yarn.proto.YarnServiceProtos.RegisterApplicationMasterRequestProto request,
com.google.protobuf.RpcCallback<org.apache.hadoop.yarn.proto.YarnServiceProtos.RegisterApplicationMasterResponseProto> done);
   //告知RM,应用已结束
public abstract void finishApplicationMaster(
com.google.protobuf.RpcController controller,
org.apache.hadoop.yarn.proto.YarnServiceProtos.FinishApplicationMasterRequestProto request,
com.google.protobuf.RpcCallback<org.apache.hadoop.yarn.proto.YarnServiceProtos.FinishApplicationMasterResponseProto> done);
   //向RM申请/归还资源,维持心跳
  public abstract void allocate(
com.google.protobuf.RpcController controller,
org.apache.hadoop.yarn.proto.YarnServiceProtos.AllocateRequestProto request,
com.google.protobuf.RpcCallback<org.apache.hadoop.yarn.proto.YarnServiceProtos.AllocateResponseProto> done);

客户端向RM提交应用后,RM会根据提交的信息,分配一定的资源来启动AM,AM启动后调用ApplicationMasterProtocol协议的registerApplicationMaster方法主动向RM注册。完成注册后,AM通过ApplicationMasterProtocol协议的allocate方法向RM申请运行任务的资源,获取资源后,通过ContainerManagementProtocol在NM上启动资源容器,完成任务。应用完成后,AM通过ApplicationMasterProtocol协议的finishApplicationMaster方法向RM汇报应用的最终状态,并注销AM。

需要注意的是,ApplicationMasterProtocol#allocate()方法还兼顾维持AM-RM心跳的作用,因此,即便应用运行过程中有一段时间无需申请任何资源,AM都需要周期性的调用相应该方法,以避免触发RM的容错机制。

其次是AM-NM

AM通过ContainerManagementProtocol协议与NM交互,包括3个方面的功能:启动容器、查询容器状态、停止容器

//启动容器      
public abstract void startContainers(
com.google.protobuf.RpcController controller,
org.apache.hadoop.yarn.proto.YarnServiceProtos.StartContainersRequestProto request,
com.google.protobuf.RpcCallback<org.apache.hadoop.yarn.proto.YarnServiceProtos.StartContainersResponseProto> done);
//查询容器状态      
public abstract void getContainerStatuses(
com.google.protobuf.RpcController controller,
org.apache.hadoop.yarn.proto.YarnServiceProtos.GetContainerStatusesRequestProto request,
com.google.protobuf.RpcCallback<org.apache.hadoop.yarn.proto.YarnServiceProtos.GetContainerStatusesResponseProto> done);
//停止容器      
public abstract void stopContainers(
com.google.protobuf.RpcController controller,
org.apache.hadoop.yarn.proto.YarnServiceProtos.StopContainersRequestProto request,
com.google.protobuf.RpcCallback<org.apache.hadoop.yarn.proto.YarnServiceProtos.StopContainersResponseProto> done);

AM通过ContainerManagementProtocol# startContainers()方法启动一个NM上的容器,AM通过该接口向NM提供启动容器的必要配置,包括分配到的资源、安全令牌、启动容器的环境变量和命令等,这些信息都被封装在StartContainersRequest中。NM收到请求后,会启动相应的容器,并返回启动成功的容器列表和失败的容器列表,同时还返回其上相应的辅助服务元数据


至此,就剩下NM上container的MAP和REDUCE过程了。


本文图文大量摘自:

http://my.oschina.net/u/1434348/blog/193374?p=1

http://dongxicheng.org/

只为学习,无意侵权


突然发现我能看懂董的博客上的绝大部分文章了


hadoop2 作业执行过程之yarn调度执行的更多相关文章

  1. hadoop2 作业执行过程之作业提交

    hadoop2.2.0.centos6.5 hadoop任务的提交常用的两种,一种是测试常用的IDE远程提交,另一种就是生产上用的客户端命令行提交 通用的任务程序提交步骤为: 1.将程序打成jar包: ...

  2. hadoop2 作业执行过程之map过程

    在执行MAP任务之前,先了解一下它的容器和它容器的领导:container和nodemanager NodeManager NodeManager(NM)是YARN中每个节点上的代理,它管理Hadoo ...

  3. Hadoop生态圈-Oozie实战之逻辑调度执行多个Job

    Hadoop生态圈-Oozie实战之逻辑调度执行多个Job 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 1>.启动hadoop集群 [root@yinzhengjie ha ...

  4. 查看yarn当前执行任务列表

    Author: kwu 查看yarn当前执行任务列表.可使用例如以下命令查看: yarn application -list 如需杀死当前某个作业,使用kill application-id的命令例如 ...

  5. 理解Yarn的执行流程和组件作用

    Yarn引入案例 1.学生找院长报到,院长给学生一个学号 2.院长比较忙,继续找主任处理学生事务 3.系主任找院办给学生分配资源(书本) 4.主任找张老师教授java 5.张老师给学生安排座位 6.学 ...

  6. Directx11教程(53) D3D11管线(8) GS的调度执行

    原文:Directx11教程(53) D3D11管线(8) GS的调度执行        在前面的教程中,我们分析了VS-PS的shader管线组合执行过程,本章我们分析一下VS-GS-PS的管线执行 ...

  7. 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 百篇博客分析OpenHarmony源码 | v7.07

    百篇博客系列篇.本篇为: v07.xx 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调 ...

  8. Kettle_使用Pan.bat执行转换、Kitchen.bat执行作业

    参考资料:http://www.cnblogs.com/wxjnew/p/3620792.html 注意:使用bat文件执行速度比执行在spoon.bat中执行慢很多 一.使用Pan.bat执行转换 ...

  9. YARN调度器(Scheduler)详解

    理想情况下,我们应用对Yarn资源的请求应该立刻得到满足,但现实情况资源往往是有限的,特别是在一个很繁忙的集群,一个应用资源的请求经常需要等待一段时间才能的到相应的资源.在Yarn中,负责给应用分配资 ...

随机推荐

  1. jq 选项卡

    <!doctype html> <html> <head> <meta charset="utf-8"> <style> ...

  2. 在WP8上搭建cocos2d-x开发环境

    在WP8上搭建cocos2d-x开发环境 转自:https://github.com/koowolf/cocos-docs/blob/master/manual/framework/native/in ...

  3. 2013年度Python Git工具

    Pycoders周刊根据读者对周刊文章的点击数据,评选出了2013年最受关注的和Git相关的Python工具. git-workflow (github.com) 可视化你的 git 工作流程的工具, ...

  4. socket的一个错误的解释SocketException以及其他几个常见异常

    写socket程序有可能会遇见这个问题  其他信息: 由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受.  这种情况我的 错误原因 ...

  5. poj 1247 The Perfect Stall 裸的二分匹配,但可以用最大流来水一下

    The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16396   Accepted: 750 ...

  6. WIN7建立wifi热点及无法启动承载网络的解决办法

    1,根据网络共享的方法,最简单莫过于利用Win7的虚拟网卡来做热点,而不用借助其他软件.         首先,用管理员身份打开CMD命令提示符,输入 netsh wlan set hostednet ...

  7. spring+jpg环境下,spring实现文件下载web实现通用的文件下载方法

    jar包复制到WEB-INF 文件夹lib下: commons-io-1.3.2.jar public static String download(HttpServletRequest reques ...

  8. Label & TextBlock

    I always thought it was odd that WPF has both TextBlock and Label.  They both are responsible for di ...

  9. 通过SimpleAction显示一个listview

    private void simpleAction1_Execute(object sender, SimpleActionExecuteEventArgs e) { IObjectSpace os ...

  10. Ruby学习资源汇总

    from:http://segmentfault.com/a/1190000000362058 Ruby 语言 Try Ruby: 无需在你的系统中安装.Ruby,只要通过浏览器便可立即体验 Ruby ...