hadoop客户端提交作业代码解读


客户端提交作业:
YarnRunner.submitApplication()
   YarnClientImpl.submitApplication
      ApplicationClientProtocal.submitApplication()  提交到RM端


在服务端,ResourceManager 里的组件   ClientRMService实现了ApplicationClientProtocal

ClientRMService.submitApplication
   RMAppManager.sbumitApplication
   创建APP,并加入到RMApps的map中,触发: RMAppEventType.START事件,该事件处理器是在ResourceManager中注册的 ApplicationEventDispatcher来处理。
   ApplicationEventDispatcher 通过事件中的appId, 从RMApps中获取 RMAppImpl,由RMAppImpl.handle处理,里面触发RMAppImpl的状态机来处理。
       RMAppImpl的状态机 调用StateStore.storeNewApplication(app)
           触发RMStateStoreAppEvent事件   RMStateStoreEventType.STORE_APP
           RMStateStore也有一个状态机,保存完appState之后,触发事件 RMAPPEventType.APP_NEW_SAVED
               RMAppImpl的状态机处理,触发 AppAddedScheduleEvent SchedulerEventType.APP_ADDED
               ResourceManager的调度器Scheduler来处理 SchedulerEventType.APP_ADDED, 简化主流程分析,我们使用FifoScheduler来进行分析
                   FifoScheduler触发RMAppEventType.APP_ACCEPTED事件
                       RMAppImpl的状态机触发,调用app.createAndStartNewAttempt(),创建一个RMAppAttemp, 触发RMAppAttemptEventType.START 事件 RMAppAttemp 的状态是NEW
                           RMAppImpl的状态机触发,调用ApplicationMasterService注册该RMAppAttempt, 并触发事件 AppAttemptAddedSchedulerEvent : SchedulerEventType.APP_ATTEMPT_ADDED
                               FifoScheduler 创建一个FiCaSchedulerApp, application设置当前的appAttemp为FiCaScheudlerApp, 触发RMAppAttemptEventType.ATTEMPT_ADDED
                                   RMAppAttemptImpl 处理该事件,调用scheduler.allocate方法 allocate Allocation.调用SchedulerApplicaitonAttempt的pullNewlyAllocatedContainersAndNMTokens方法
                                      SchedulerApplicaitonAttempt.pullNewlyAllocatedContainersAndNMTokens() 
                                      如果有资源,就触发RMContainerEventType.ACQUIRED. SchedulerApplicaitonAttempt的资源newlyAllocatedContainers来自NodeManager的给ResourceManager的心跳请求,后面会详细分析
                                         RMContainerImpl处理RMContainerEventType.ACQUIRED 事件,触发RMAppRunningOnNodeEvent : RMAppEventType.APP_RUNNING_ON_NODE
                                            RMAppImpl处理RMAppEventType.APP_RUNNING_ON_NODE, 
                                   
                           
                       

NodeManager如何发送HeartBeat给ResourceManager?

NodeManager是通过组件NodeStatusUpdaterImpl发送的。
               
NodeStatusUpdaterImpl里有一个线程 statusUpdaterRunable,定期的发送心跳给NodeManager,发送心跳的协议: ResourceTracker


ResourceManager处理NodeManager的心跳:

ResourceTrackerService实现了ResourceTracker的协议
ResourceTrackerService.nodeHeartbeat方法, 触发RMNodeEventType.STATUS_UPDATE事件,
RMNodeImpl里的状态机会处理RMNodeEventType.STATUS_UPDATE 事件, 触发SchedulerEventType.NODE_UPDATE事件
    Scheduler.nodeUpdate
        completedContainer, 触发RMContainerEventType.FINISHED 事件
        assignContainers(node)
            FiCaSchedulerApp.allocate()
               rmContainer = new RMContainerImpl()
               newlyAllocatedContainers.add(rmContainer)
               触发RMContainerEventType.START
                   RMContainerImpl处理 RMContainerEventType.START 事件,
                       触发 RMAPPAttemptEventType.CONTAINER_ALLOCATED事件
                           RMAPPAttemptImpl 处理 RMAPPAttemptEventType.CONTAINER_ALLOCATED事件
                               appAttempt.scheudler.allocate(...)
                                   FiCaSchedulerApp application = getApplicationAttempt(...)
                                   allocation = application.pullNewlyAllocatedContainersAndNMtokens();
                                       for(Container contaner : newlyAllocatedContainers)
                                       {
                                           rmContainer.handler(new RMContainerEvent(rmContainer.getContainerId(), RMContainerEventType.ACQUIRED))
                                           触发RMAppEventType.APP_RUNNING_ON_NODE事件
                                       }
                                appAttempt.storeAttempt()
                                    rmContext.getStateStore().storeNewApplicationAttempt(this);
                                    触发 new RMStateStoreAppAttemptEvent(attemptState) : RMStateStoreEventType.STORE_APP_ATTEMPT
                                        RMStateStore 处理该事件,并发出 RMAppAttemptEventType.ATTEMPT_NEW_SAVED 事件
                                           RMAPPAttemptImpl 处理,调用 appAttempt.launchAttempt(); 触发 AMLauncherEventType.LAUNCH事件
                                              ApplicationMasterLauncher处理 createRunableLaucher
                                                   AMLauncer.launcher(), connect()调用建立ContainerManagementProtocal的proxy, 创建一个ContainerLauncherContext, 并调用 proxy.startContainers(..)
                                                   ContainerManagerImpl实现了ContianerManagementProtocal
                                                   触发RMAppAttemptEventType.LAUNCHED
                                                   
                                           
                                    
                                    
                                    

                                
                                           
                                           
                   
          
        
    
   

启动Container

ContainerManagerImpl实现了ContianerManagementProtocal

ContainerManagerImpl.startContainers()
    startContainersInternal
        Application application = newApplicaitonImpl(...)
        context.getNMStateStore().storeApplication();
        触发事件: ApplicaitonInitEvent: ApplicationEventType.INIT_APPLICATION
            ApplicationImpl处理, 触发事件:LogHandlerAppStartedEvent: LogHandlerEventType.APPLICATION_STARTED.
                LogAggregationService处理, InitApp ,触发事件:ApplicationEventType.APPLICATION_LOG_HANDLING_INITED
                    ApplicationImpl处理, 触发 LocalizationEventType.INIT_APPLICATION_RESOURCES
                       ResourceLocalizationService.handler(...) 
                           hanldeInitApplicaitonResources(...)
                               privateRsrc.putifAbsent(userName, new LocalResourcesTrackerImpl(...))
                               appRsrc.putifAbsent(appIdStre, new LocalResourcesTrackerImpl(...))
                               触发 ApplicationEventType.APPLICATION_INITED
                                   ApplicationImpl处理,
                                   for(Container container : app.containers.values()) {
                                       app.dispatcher.getEVentHandler().handler(new ContainerInitEvent(container.getContainerId()))
                                   }
                                   
                                      ContainerImpl
                                          构造LocalResourceREquest req
                                          container.dispatcher.getEVentHandler().handler( new ContainerLocalizationRequestEvent(container,req))  LocalizationEventType.INIT_CONTAINER_RESOURCES
                                              ResourceLocalizationService.handleInitContainerREsources(...)
                                                  for(LocalREsourceREquest req : event.getRequestedResources())
                                                  {
                                                      LocalResourcesTracker tracker = getLocalResourcesTracker(...);
                                                      tracker.handler(new ResourceRequestEvent(req,...)) : ResourceEventType.REQUEST
                                                  }
                                                  
                                                       LocalizedResource 处理 ResourceEventType.REQUEST
                                                       rsrc.dispatcher.getEVentHandler().handler(new LocalizerResourceREquestEvent(...))  LocalizationEventType.REQUEST_RESOURCE_LOCAIZATION
                                                            ResourceLocalizationService处理事件 
                                                               如果是PUBLIC publicLocalizer.addResource(req);
                                                               如果是PRIVATE 或者APPLICATION,privLocalizers.get(locId); 为空就创建一个 localizer = new LocalizerRunner(...);
                                                                 LocalizerRunner.run(){
                                                                    ContainerExecutor.startLocalizer(...) ContainerExecutor 的实现是LinuxContainerExecutor
                                                                    LinuxContainerExecutor.startLocalizer(...)
                                                                    构造了一个命令: 调用 ContainerLocalizer.main(String[] args)
                                                                       ContainerLocalizer.runLocalization(...)
                                                                           localizeFiles(...)
                                                                               while线程定期的像nodemanager.heartbeat(status), 告诉nodemanager哪些下载好了  LocalizationProtocal
                                                                               threadpool.submit(downoad(new Path(....)))
                                                                                  downoad()返回一个new FsDownload线程
                                                                                     FsDownload.call(...)把文件从hdfs下载到本地
                                                                                     
                                                                            ResourceLocalizationService 实现了 LocalizationProtocal    
                                                                               heartbeat(LocalizerStatus status)
                                                                                   localizerTracker.processHeartbeat(status);
                                                                                      privLocalizers.get(locId).processHeartbeat(status);
                                                                                         for(LocalResourceStatus stat : remoteResourceStatuses) {
                                                                                             case FETCH_SUCCESS: 
                                                                                                 触发 new ResourceLocalizedEvent(...)  ResourceEventType.LOCALIZED
                                                                                                     LocalREsourcesTrackerImpl处理
                                                                                                         LocalizedResource rsrc = localrsrc.get(req);
                                                                                                         rsrc.hanlder(event);
                                                                                                             for(ContainerId container: refs.ref) {
                                                                                                                 rsrc.dispatcher.getEVentHandler().handler(new ContanerResourceLocalizedEvent(...))  ContainerEventType.RESOURCE_LOCALIZED
                                                                                                             }
                                                                                                             
                                                                                                                 ContainerImpl处理事件ContainerEventType.RESOURCE_LOCALIZED
                                                                                                                 LocalizedTransition.transition()
                                                                                                                     List<String> syms = container.pendingREsources.remove(rsrcEvent.getResource());
                                                                                                                     如果syms空了,触发事件 LocalizationEventType.CONTAINER_RESOURCES_LOCALIzED.
                                                                                                                          ResourceLocalizationService 处理  LocalizationEventType.CONTAINER_RESOURCES_LOCALIzED.
                                                                                                                              ResourceLocalizationService.handleContainerResourcesLocalized(...);
                                                                                                                                  localizerTracker.endContainerLocalization(locId);
                                                                                                                                      privLocalizers.get(locId).endContainerLocalization();
                                                                                                                    contianer.sendLaunchEvent();
                                                                                                                         ContainersLauncherEventType.LAUNCH_CONTAINER
                                                                                                                         
                                                                                                                            ContainersLauncher 处理, 
                                                                                                                              Application app = context.getApplications().get(applicationId);
                                                                                                                              ContainerLaunch launch = new ContainerLauch(....);
                                                                                                                              containerLauncher.submit(launch);// containerLauncher是一个线程池
                                                                                                                                ContainerLaunch.call(){
                                                                                                                                    构造运行的命令
                                                                                                                                    LinuxContainerExecutor.launchContainer(....);
                                                                                                                                }
                                                                                                                                  
                                                                                                         
;
                                                                                         }
                                                                                      
                                                                                  
                                                                            
                                                                    
                                                                 }
                                                               
                                                            
                                                       
                              
                          
        context.getNMStateStore().storeContainer(...);
        触发事件: ApplicaitonContainerInitEvent(container); ApplicationEventType.INIT_CONTAINER
        

MRAppMaster.main
   MRAppMaster appMaster = new MRAppMaster(...)//从参数中获取applicationAttemptId, containerId,... 构造一个MRAppMaster
   JobConf conf = new JobConf(new YarnConfiguration())
   conf.addREsource(new Path(job.xml));
   initAndStartAppMaster(appMaster, conf,jobUserName)
       appMaster.init(conf);
       appMaster.start() == appMaster.serverStart()
          createJob(); //job = new JobImpl(...)
          触发JobEventType.JOB_INIT事件
          如果初始化成功,调用startJob() == 发送JobEventType.JOB_START 事件
          JobImpl.StartTransition.transition()// 
              触发 new CommitterJobSetupEvent() : CommitterEventType.JOB_SETUP
                 CommitterEventHanlder.handleJobSetup(); //设置JobCommitter的环境
                    触发JobEventType.JOB_SETUP_COMPLETED
                       JobImpl.SetupCompletedTransition.transition()
                           job.scheduleTasks(job.mapTasks, job.numReduceTasks == 0 ) //触发 new TaskEvent(taskID, TaskEventType.T_SCHEDULE);
                           job.scheduleTasks(job.reduceTasks, true)  //触发 new TaskEvent(taskID, TaskEventType.T_SCHEDULE);
                               TaskImpl.InitialScheduleTransition.transition()
                                  task.addAndScheduleAttempt(Avataar.VIRGIN);
                                      TaskAttempt attempt = addAttempt(avataar);
                                      eventHandler.handle(new TaskAttemptEvent(attempt.getID(), TaskAttemptEventType.TA_SCHEDULE));
                                         TaskAttempImpl.RequestContainerTransition.transition()
                                             触发new ContainerRequestEvent(...) : ContainerAllocator.EventType.CONTAINER_REQ
                                                 RMContainerAllocator.hanlde() 把Event加入queue, 然后在while循环从queue中取出Event处理。
                                                     RMContainerAllocator.hanldeEvent(event);
                                                     如果是map handleMapContainerRequest();
                                                     如果是Reduce handleReduceContainerRequest()
                                                         ScheduledRequests.addMap(reqEvent); //
                                                            addContainerReq(request);
                                                            在RMCommunicator里有一个ContainerAllocatorThread, 定期的调用heartbeat, RMContainerAllocator 是RMCommunicator 的子类,调用的是RMCommunicator.heartbeat()
                                                               List<Container> allocatedContainers = getResources(); //从RM获取Containers
                                                               scheduledRequests.assign(allocatedContainers)
                                                                  assignContainers(allocatedContainers)
                                                                  releaseContainsers if not not assign
                                                                     assignMapsWithLocality(allocatedContainers);
                                                                        containerAssigned(allocated, assigned)
                                                                           触发 new TaskAttemptContainerAssignedEvent : TaskAttemptEventType.TA_ASSIGNED
                                                                              TaskAttempImpl.ContainerAssignedTransition.transition()
                                                                                  创建一个ContainerLaunchContext, 并触发 new ContainerRemoteLaunchEvent() : ContainerLauncher.EventType.CONTAINER_REMOTE_LAUNCH 事件
                                                                                      ContainerLauncherImpl处理,
                                                                                          Container c = getContainer(event); 
                                                                                          ContainerRemoteLaunchEvent launchEvent = (ContainerRemoteLaunchEvent)event;
                                                                                          c.launch(launchEvent)
                                                                                             ContainerManagementProtocal proxy = getProxy(...);
                                                                                             proxy.startContainers();
                                                               
                                             
                                             
                                      
                                 
                    
                    
               
          
          
          
       
      
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值