Yarn源码剖析(三)--- ApplicationMaster的启动

本文深入剖析了Yarn中ApplicationMaster(AM)的启动过程,从spark-submit提交任务开始,详细讲解了如何通过YarnClient提交应用、AM启动、Container的申请等步骤,涉及Yarn的事件处理机制、状态机转换等关键环节。
摘要由CSDN通过智能技术生成

前言

在上文Yarn源码剖析(二) --- spark-submit,我们介绍了spark任务通过spark-submit提交任务至yarn申请资源至启动的全流程,本篇将介绍启动过程中ApplicationMaster(后文简称AM)是如何启动。

AM的启动与Container的申请

1. 在Yarn源码剖析(二)中yarnClient最终调用submitApplication方法提交任务,传入的参数带有AM启动的上下文,因此AM的启动就是在yarn这个方法中实现的

val containerContext = createContainerLaunchContext(newAppResponse) //封装AM启动的上下文
val appContext = createApplicationSubmissionContext(newApp, containerContext) //App的上下文

yarnClient.submitApplication(appContext) //提交任务

2. AM的启动异常的复杂,篇幅巨大,下面我会摘选重要的部分做分析,spark在此处封装好AM运行的上下文后,最终在yarn的事件处理机制会运行这些上下文,回调到spark中的AM类,client模式和cluster模式运行的类是不一样的,具体的运行类如下所示:

val amClass =
 if (isClusterMode) { //集群cluster模式
    Utils.classForName("org.apache.spark.deploy.yarn.ApplicationMaster").getName
 } else { //client模式
    Utils.classForName("org.apache.spark.deploy.yarn.ExecutorLauncher").getName
 }

3. 那显而易见的,我们应该从yarnClient.submitApplication(appContext)去分析hadoop端的代码,分析yarn是如何来通过这个上下文来启动spark自己封装的这个AM的,显而易见这个接口由YarnClientImpl实现,在该方法内部又调用了ApplicationClientProtocol.submitApplication,这个类是yarn利用rpc相互通信的关键类,这里也不多做介绍了,我们看到提交任务后会启动一个死循环,等待任务提交完成。

//request是包含了我们服务整体参数以及脚本的对象,提交至RM
 rmClient.submitApplication(request);

 int pollCount = 0;
 long startTime = System.currentTimeMillis();
 EnumSet<YarnApplicationState> waitingStates = 
 EnumSet.of(YarnApplicationState.NEW,
 YarnApplicationState.NEW_SAVING,
 YarnApplicationState.SUBMITTED);
 EnumSet<YarnApplicationState> failToSubmitStates = 
 EnumSet.of(YarnApplicationState.FAILED,
 YarnApplicationState.KILLED); 
 while (true) {
     try {
         ApplicationReport appReport = getApplicationReport(applicationId);
         YarnApplicationState state = appReport.getYarnApplicationState();
         if (!waitingStates.contains(state)) {
             if(failToSubmitStates.contains(state)) {
                 throw new YarnException("Failed to submit " + applicationId + 
                 " to YARN : " + appReport.getDiagnostics());
             }
         LOG.info("Submitted application " + applicationId);
         break;
     }
}

4. 这个submitApplication是由ClientRMService来实现的,我把整段方法都贴进来了,所以我把分析内容放到了代码的注释中

//为了保证安全性ApplicationSubmissionContext在这里会被验证,哪些独立于RM
 //字段在此处验证,而依赖于RM发的则在RMAppManager被验证
String user = null;
try {
     user = UserGroupInformation.getCurrentUser().getShortUserName();
} catch (IOException ie) {
    LOG.warn("Unable to get the current user.", ie);
    RMAuditLogger.logFailure(user, AuditConstants.SUBMIT_APP_REQUEST,
    ie.getMessage(), "ClientRMService",
    "Exception in submitting application", applicationId);
    throw RPCUtil.getRemoteException(ie);
 }

 //确认app是否被放在了rmContext中,如果是则响应
if (rmContext.getRMApps().get(applicationId) != null) {
 LOG.info("This is an earlier submitted application: " + applicationId);
 return SubmitApplicationResponse.newInstance();
 }

 //判断任务队列
if (submissionContext.getQueue() == null) {
 submissionContext.setQueue(YarnConfiguration.DEFAULT_QUEUE_NAME);
 }
 //判断是否是无效的任务名称
if (submissionContext.getApplicationName() == null) {
 submissionContext.setApplicationName(
 YarnConfiguration.DEFAULT_APPLICATION_NAME);
 }
 //任务类型判断
if (submissionContext.getApplicationType() == null) {
 submissionContext
 .setApplicationType(YarnConfiguration.DEFAULT_APPLICATION_TYPE);
 } else {
     if (submissionContext.getApplicationType().length() >                 
     YarnConfiguration.APPLICATION_TYPE_LENGTH) {
     submissionContext.setApplicationType(submissionContext
     .getApplicationType().substring(0,
     YarnConfiguration.APPLICATION_TYPE_LENGTH));
     }
 }

 try {
 // call RMAppManager to submit application directly
 //让RMAppManager立即提交应用
//关于ApplicationManager大家可以参考我基础组件分析的那一章节
 rmAppManager.su
  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值