hadoop任务调度详解

 

                                                          hadoop任务调度详解

    任何作业的运行,首先得从用户端提交作业给jobTracker开始。

    用户端:
         用户程序通过job类的submit方法向jobTracker提交作业,job类使用jobClient类来做一系列工作.

扫描二维码关注公众号,回复: 702885 查看本文章

        (1)向jobTracker申请作业ID号。

        (2)检查作业的输出格式是否正确,比如作业的输出目录是否存在或已经存在,若输出格式不正确,会将错误信息返回给用户端的控制台。(实际我们也经常遇到这种错误,the directory already exists.)


        (3)检查输入目录是否存在。

        (4)创建job.split,job.xml文件,将这些文件放在该job对应ID号的目录下。(每个Job在hdfs上会有对应的ID的目录)

         (5)根据input format格式获得相应的input split,将input split信息写入到job.split文件中。(input split信息包括split的大小,split的内容,此split在文件的位置,以及此split在哪个datanode下。)

         (6)将job所需的jar包上传到hdfs上,并且将job的配置信息写入到job.xml文件中.

          (7)将job提交给jobTracker.

    JobTracker

       在jobTracker的构造函数中,会生成taskScheduler成员变量,该成员变量负责调度job,它默认格式是JobQueueTaskScheduler,它采用的是FIFO的调度方式,在jobTracker的offService()中调用taskScheduler.start()方法,在该start()方法中有两个监听器 ,一个是jobQueueJobInprogressListener(用于监听job的运行),一个是eagerTaskInitializationListener(用于对job的初始化),在eagerTaskInitializationListener中启动一个jobInitManagerThread线程,不断从jobInitQueue队列中得到jobInProgress对象,调用jobInprogress中的initTasks()方法完成job初始化,jobInprogress对象是在job提交给jobTracker时通过调用jobAdd()方法添加到jobInitQueue队列中的。initTasks()方法中主要实现的操作有:

  (1)从hdfs上读取job.split文件从而生成input splits.设定map Task的个数(也就是input splits的个数)。

 (2)为每个map task生成TaskInprogress对象.

            

         maps[i] = new TaskInProgress(jobId, jobFile, 
                                   splits[i], 
                                   jobtracker, conf, this, i, numSlotsPerMap);

  

(3)在将这些map task放入到nonRunningMapCache中.(当taskTracker具备运行map task环境时,直接从cache中取)。

(4)为每个reduce task生成TaskInprogress对象,并将其放入到nonRunningReduces中(当taskTracker具备运行reduce task环境时,直接从nonRunningReduces中取)。

(5)创建两个cleanup task,一个用于清理map ,一个用于清理reduce.

(6)创建两个setup task,一个初始化map,一个初始化reduce.

当jobTracker收到taskTracker调用heartbeat()方法后,首先会检查上一次心跳是否完成,如果一切正常,则会处理心跳。jobTracker会调用taskScheduler组装任务到任务列表中,具体实现在asignTasks()方法中,tasks = taskScheduler.assignTasks(taskTrackers.get(trackerName));得到这些任务之后,便将其封装在一些LauchTaskAction中,发回给taskTracker,让它去执行。

TaskTracker

taskTracker会每隔一段时间通过调用transmitHeartBeat()方法放送一次心跳给jobTracker,在transmitHeartBeat()方法中,taskTracker首先会检查目前执行task的任务以及磁盘的使用情况,

askForNewTask = 
        ((status.countOccupiedMapSlots() < maxMapSlots || (当前taskTracker运行map或reduce task的个数小于最大可运行的map 或reduce task的个数)
          status.countOccupiedReduceSlots() < maxReduceSlots) && 
         acceptNewTasks);  localMinSpaceStart = minSpaceStart;

如果可以接收新的任务,则将askForNewTask参数设置成true.向jobTracker发送心跳。

HeartbeatResponse heartbeatResponse = jobClient.heartbeat(status, 
                                                              justStarted,
                                                              justInited,
                                                              askForNewTask, 
                                                              heartbeatResponseId);

 

这是RPC的调用,获得hearbeatResponse信息。通过调用heartbeatResponse.getActions()获得jobTracker传过来的taskTrackerAction数组.遍历数组,看是否具有launchTaskAction,如果有则将其加入到队列中,调用addToTaskQueue,如果是map task,则放入到mapLaucher中,如果是reduce task,则放入到reduceLaucher中。taskLaucher是一个线程,它从以上队列中获得taskInprogress对象,然后调用startNewTask()方法来启动一个task.该task启动时,会将该task运行所需要的文件(job.xml,job.split,job.jar)从hdfs上拷贝到本地文件系统中。

猜你喜欢

转载自willyii.iteye.com/blog/1405537