【Hadoop篇】YARN源码分析(二)

0、回顾【Hadoop篇】YARN源码分析(一)

NodeManager启动了MRAppMaster(MRAppMaster就是ApplicationMaster的一种实现)

1、MRAppMaster统一管理这个Job的所有Task

1.MRAppMaster启动RMContainerAllocator服务
2.MRAppMaster注册、初始化、启动JobImpl
3.JobImpl创建MapTask和ReduceTask,并提交给TaskImpl
4.TaskImpl将Task提交给TaskAttemptImpl,TaskAttemptImpl提交给RMContainerAllocator处理

public class MRAppMaster extends CompositeService {
    public static void main(String[] args) {
        MRAppMaster appMaster = new MRAppMaster(applicationAttemptId, containerId, nodeHostString, Integer.parseInt(nodePortString), Integer.parseInt(nodeHttpPortString), appSubmitTime);
        initAndStartAppMaster(appMaster, conf, jobUserName);
        ->appMaster.init(conf);
        ->appMaster.start();
          ->serviceStart();
    }
    
    protected void serviceStart() throws Exception {
        job = createJob(getConfig(), forcedState, shutDownMessage);
        ->Job newJob = new JobImpl(jobId, appAttemptID, conf, dispatcher.getEventHandler(),taskAttemptListener, jobTokenSecretManager, jobCredentials, clock,completedTasksFromPreviousRun, metrics,committer, newApiCommitter,currentUser.getUserName(), appSubmitTime, amInfos, context, forcedState, diagnostic);
        ->dispatcher.register(JobFinishEvent.Type.class, createJobFinishEventHandler());   
        
        JobEvent initJobEvent = new JobEvent(job.getID(), JobEventType.JOB_INIT);
        jobEventDispatcher.handle(initJobEvent);
        ->TaskSplitMetaInfo[] taskSplitMetaInfo = createSplits(job, job.jobId);  --【JobImpl】
        ->job.numMapTasks = taskSplitMetaInfo.length;  --【JobImpl】
        ->job.numReduceTasks = job.conf.getInt(MRJobConfig.NUM_REDUCES, 0);  --【JobImpl】
        ->createMapTasks(job, inputLength, taskSplitMetaInfo); //创建MapTask
          ->for (int i=0; i < job.numMapTasks; ++i)
            ->TaskImpl task = new MapTaskImpl(job.jobId, i,...)  --【JobImpl】
            ->job.addTask(task);  --【JobImpl】
              ->tasks.put(task.getID(), task);      --【JobImpl】
        ->createReduceTasks(job);  //创建ReduceTask
        
        startJobs();
        ->JobEvent startJobEvent = new JobStartEvent(job.getID(), recoveredJobStartTime);
          ->super(jobID, JobEventType.JOB_START);
        ->dispatcher.getEventHandler().handle(startJobEvent);
          ->job.eventHandler.handle(new CommitterJobSetupEvent(job.jobId, job.jobContext));  --【JobImpl.StartTransition】
            ->super(CommitterEventType.JOB_SETUP);
            ->handleJobSetup((CommitterJobSetupEvent) event);  --【CommitterEventHandler.EventProcessor】
              ->context.getEventHandler().handle(new JobSetupCompletedEvent(event.getJobID()));  --【CommitterEventHandler.EventProcessor】
                ->super(jobID, JobEventType.JOB_SETUP_COMPLETED);
                //向TaskImpl提交MapTask
                ->job.scheduleTasks(job.mapTasks, job.numReduceTasks == 0);   --【JobImpl.SetupCompletedTransition】
                  ->for (TaskId taskID : taskIDs) 
                    ->eventHandler.handle(new TaskEvent(taskID, TaskEventType.T_SCHEDULE));
                //向TaskImpl提交ReduceTask    
                ->job.scheduleTasks(job.reduceTasks, true);    
    }
    
    private final class ContainerAllocatorRouter extends AbstractService implements ContainerAllocator, RMHeartbeatHandler {
        private final ClientService clientService;
        private final AppContext context;
        private ContainerAllocator containerAllocator;

        protected void serviceStart() throws Exception {
            this.containerAllocator = new RMContainerAllocator(this.clientService, this.context, preemptionPolicy);
            ((Service)this.containerAllocator).init(getConfig());
            ((Service)this.containerAllocator).start();
        }
        
        public void handle(ContainerAllocatorEvent event) {
             this.containerAllocator.handle(event);
        }
    }
}
public abstract class TaskImpl implements Task, EventHandler<TaskEvent> {
    .addTransition(TaskStateInternal.NEW, TaskStateInternal.SCHEDULED, TaskEventType.T_SCHEDULE, new InitialScheduleTransition())
    
    private static class InitialScheduleTransition implements SingleArcTransition<TaskImpl, TaskEvent> {
        public void transition(TaskImpl task, TaskEvent event) {
            task.addAndScheduleAttempt(Avataar.VIRGIN);
            ->addAndScheduleAttempt(avataar, false);
              ->eventHandler.handle(new TaskAttemptEvent(attempt.getID(), TaskAttemptEventType.TA_SCHEDULE));
        }
    }   
}
public abstract class TaskAttemptImpl implements org.apache.hadoop.mapreduce.v2.app.job.TaskAttempt,EventHandler<TaskAttemptEvent> {
    .addTransition(TaskAttemptStateInternal.NEW, TaskAttemptStateInternal.UNASSIGNED,TaskAttemptEventType.TA_SCHEDULE, new RequestContainerTransition(false))
    
    static class RequestContainerTransition implements SingleArcTransition<TaskAttemptImpl, TaskAttemptEvent> {
        public void transition(TaskAttemptImpl taskAttempt, TaskAttemptEvent event) {
            taskAttempt.eventHandler.handle(new ContainerRequestEvent(taskAttempt.attemptId, taskAttempt.resourceCapability,taskAttempt.dataLocalHosts.toArray(new String[taskAttempt.dataLocalHosts.size()]),taskAttempt.dataLocalRacks.toArray(new String[taskAttempt.dataLocalRacks.size()])));
            ->super(attemptID, ContainerAllocator.EventType.CONTAINER_REQ);
            ->eventQueue.put(event);  --eventHandlingThread去取【RMContainerAllocator 】
        }
    }
}

2、RMContainerAllocator根据Task创建Container

1.RMContainerAllocator调用ApplicationMasterProtocol的registerApplicationMaster向ResourceManager注册ApplicationMaster
2.RMContainerAllocator不断heartbeat检查,通过ApplicationMasterProtocol的allocate向ResourceManager申请Container资源
3.如果Container资源申请成功,则运行处理的Task
4.如果MapTask全部处理完成,则开始执行pendingReduces中的ReduceTask

public class RMContainerAllocator extends RMContainerRequestor implements ContainerAllocator {
   protected void serviceStart() throws Exception {
       this.eventHandlingThread = new Thread() {
           public void run() {
               while (!stopped.get() && !Thread.currentThread().isInterrupted()) {
                   event = RMContainerAllocator.this.eventQueue.take();
                   handleEvent(event);
                   ->if (event.getType() == ContainerAllocator.EventType.CONTAINER_REQ) 
                     ->if (isMap) 
                      ->handleMapContainerRequest(reqEvent);
                        ->scheduledRequests.addMap(reqEvent); 
                    ->else
                      ->handleReduceContainerRequest(reqEvent);
                        ->pendingReduces.add(new ContainerRequest(reqEvent,PRIORITY_REDUCE, reduceNodeLabelExpression));  
               }
           }
       }
       this.eventHandlingThread.start();
       super.serviceStart();
       ->scheduler= createSchedulerProxy();    --【RMCommunicator】
       ->job = context.getJob(jobId);   --【RMCommunicator】
       ->register();   --【RMCommunicator】
         ->RegisterApplicationMasterResponse response = scheduler.registerApplicationMaster(request);
       ->startAllocatorThread();   --【RMCommunicator】
         ->allocatorThread = new Thread(new AllocatorRunnable());
         ->allocatorThread.start();
           ->public void run()  --【RMCommunicator.AllocatorRunnable】
             ->while (!stopped.get() && !Thread.currentThread().isInterrupted())
               ->heartbeat();
                 //获取到Container资源,则运行Containers
                 ->List<Container> allocatedContainers = getResources();   --【RMContainerAllocator】
                   ->response = makeRemoteRequest();
                     ->AllocateResponse allocateResponse = scheduler.allocate(allocateRequest);  --scheduler是ApplicationMasterProtocol
                   ->List<Container> newContainers = response.getAllocatedContainers(); 
                 ->if (allocatedContainers != null && allocatedContainers.size() > 0)
                   ->scheduledRequests.assign(allocatedContainers);  
                 ->scheduleReduces(getJob().getTotalMaps(), completedMaps,scheduledRequests.maps.size(), scheduledRequests.reduces.size(),assignedRequests.maps.size(), assignedRequests.reduces.size(),mapResourceRequest, reduceResourceRequest, pendingReduces.size(),maxReduceRampupLimit, reduceSlowStart);
                   //如果MapTask全部执行完毕,则执行ReduceTask
                   ->if (scheduledMaps == 0 && numPendingReduces > 0) 
                     ->scheduleAllReduces();
                       ->for (ContainerRequest req : pendingReduces)
                         ->scheduledRequests.addReduce(req);  
                           ->addContainerReq(req);
   }
}

3、创建脚本,将YarnChild设置为Container的启动类

1.通过ContainerManagementProtocol向NodeManager启动Container

public class RMContainerAllocator extends RMContainerRequestor implements ContainerAllocator {
   class ScheduledRequests {
       private void assign(List<Container> allocatedContainers) {
           assignContainers(allocatedContainers);
           ->Iterator<Container> it = allocatedContainers.iterator();
           ->while (it.hasNext()) 
             ->containerAssigned(allocated, assigned);
               ->eventHandler.handle(new TaskAttemptContainerAssignedEvent(assigned.attemptID, allocated, applicationACLs));
                  ->super(id, TaskAttemptEventType.TA_ASSIGNED); 
                 ->Container container = cEvent.getContainer();  --【TaskAttemptImpl.ContainerAssignedTransition】 
                 ->ContainerLaunchContext launchContext = createContainerLaunchContext(cEvent.getApplicationACLs(), taskAttempt.conf, taskAttempt.jobToken,taskAttempt.remoteTask, taskAttempt.oldJobId, taskAttempt.jvmID,taskAttempt.taskAttemptListener, taskAttempt.credentials);
                   ->List<String> commands = MapReduceChildJVM.getVMCommand(taskAttemptListener.getAddress(), remoteTask, jvmID);
                     ->vargs.add(MRApps.crossPlatformifyMREnv(task.conf, Environment.JAVA_HOME) + "/bin/java");
                     //设置YarnChild为启动类
                     ->vargs.add(YarnChild.class.getName());  // main of Child
                     ->StringBuilder mergedCommand = new StringBuilder();
                     ->for (CharSequence str : vargs)
                       ->mergedCommand.append(str).append(" ");
                     ->Vector<String> vargsFinal = new Vector<String>(1);
                     ->vargsFinal.add(mergedCommand.toString());
                     ->return vargsFinal;
                 ->taskAttempt.eventHandler.handle(new ContainerRemoteLaunchEvent(taskAttempt.attemptId, launchContext, container, taskAttempt.remoteTask));   --【TaskAttemptImpl.ContainerAssignedTransition】
                   ->Container c = getContainer(event);   --【ContainerLauncherImpl】
                   ->c.launch(launchEvent);    --【ContainerLauncherImpl】
                     ->StartContainersResponse response = proxy.getContainerManagementProtocol().startContainers(requestList);    --【ContainerLauncherImpl】
       }
   }
}

4、NodeManager通过ContainerManagementProtocol接收startContainers请求,执行脚本启动YarnChild,同【Hadoop篇】YARN源码分析(一)

public class ContainerManagerImpl extends CompositeService implements ContainerManager {
    public StartContainersResponse startContainers(StartContainersRequest requests) throws YarnException, IOException {
        ...
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值