mapreduce中jobtracker进程的分析

来源:互联网 发布:java鱼雷 编辑:程序博客网 时间:2024/05/22 00:24

 

对于JobTracker来说,主要做的事情有:

与客户端的通信:接收客户端的命令,如提交jobkill job

接收TaskTracker心跳:为TT分配Task任务队列,更新task状态,以及监测TT的状态。

内部处理操作:

job进行初始化,分解成多个map,reducetask任务。

对许多job进行排列,按照某种调度算法排列。

更新task的状态。

更新job的状态

 

submitJob

client端调用submitJob方法提交job后,通过远程调用Jobtracker进程的submitJob方法。

Jobtracker根据用户提交的信息,得到jobid,用户组及判断权限,另外将job的信息写到hdfs上,以便TT能够访问。

Addjob()

然后再调用addJob()方法,方法中会将job加入到jobs队列中,job队列采用了map数据结构,

Map<JobID,JobInProgress> jobs = new TreeMap<JobID, JobInProgress>();

可以很方便的通过jobid找到该job相应的JobInProgress对象。

同时也会加入到JobInProgressListener类中,此类主要是用来监听job的类。

完成后,最后将返回job的状态。

synchronized JobStatus addJob(JobID jobId, JobInProgress job) {

    totalSubmissions++;

    synchronized (jobs) {

      synchronized (taskScheduler) {

        jobs.put(job.getProfile().getJobID(), job);

        for (JobInProgressListener listener : jobInProgressListeners) {

          try {

            listener.jobAdded(job);

          } catch (IOException ioe) {

            LOG.warn("Failed to add and so skipping the job : "

                + job.getJobID() + ". Exception : " + ioe);

          }

        }

      }

    }

    myInstrumentation.submitJob(job.getJobConf(), jobId);

    LOG.info("Job " + jobId + " added successfully for user '"

             + job.getJobConf().getUser() + "' to queue '"

             + job.getJobConf().getQueueName() + "'");

    return job.getStatus();

  }

 

 

JobInProgressListener

JobInProgress监听接口有:

job加入,jobJT中去除,更新JT中的job。这几个操作都是由客户端或者TT发起的。

public abstract void jobAdded(JobInProgress job) throws IOException;

public abstract void jobRemoved(JobInProgress job);

public abstract void jobUpdated(JobChangeEvent event);

 

JT上有个JobInProgressListener的队列,里面有个

public void addJobInProgressListener(JobInProgressListenerlistener) {

    jobInProgressListeners.add(listener);

  }

该方法就是将相应的job监听对象放入到JT的监听队列上,然后由addjob时,分别去触发这些监听对象。

而这些监听对象的加入是由TaskScheduler实现类通过Jobtracker addJobInProgressListener()方法将相应的job监听对象加入到JT上。

TaskScheduler是任务调度器接口,由Jobtracker的构造函数时创建起来的。

/ Create the scheduler

    Class<? extends TaskScheduler> schedulerClass

      = conf.getClass("mapred.jobtracker.taskScheduler",

          JobQueueTaskScheduler.class, TaskScheduler.class);

    taskScheduler =

      (TaskScheduler)ReflectionUtils.newInstance(schedulerClass, conf);

TaskScheduler中有个start()方法来启动调度器中的初始化工作,包括job监听对象,以及相应的守护线程等。

同时该类中有个变量:

protected TaskTrackerManager taskTrackerManager;

即是jobtracker的父类,该类包含了TaskScheduler调度器与Jobtracker之间的通信,即调用接口。

mapreduce提供的默认的调度器是FIFO调度类JobQueueTaskScheduler

在该类的start()方法主要:

public synchronized void start() throws IOException {

    super.start();

  taskTrackerManager.addJobInProgressListener(jobQueueJobInProgressListener);

    eagerTaskInitializationListener.setTaskTrackerManager(taskTrackerManager);

    eagerTaskInitializationListener.start();

    taskTrackerManager.addJobInProgressListener(

        eagerTaskInitializationListener);

  }

Jobtracker增加了二个job监听对象。

一个是job队列监听类,JobQueueJobInProgressListener

还有一个是EagerTaskInitializationListenerjob初始化的监听类,即将job对象转化为maptask,reducetask对象。

接下来分析这二个类是在监听到对job的操作后是如何处理的。

JobQueueJobInProgressListener

 JobQueueJobInProgressListener类中用一个队列来存放job

  private Map<JobSchedulingInfo, JobInProgress> jobQueue;

此类就是将job加入到该队列,或者从队列中除去job,以及更新队列中job的状态。

JobQueueJobInProgressListener中该方法如下:主要是将job加入到该类中的job队列jobQueue中。jobQueue的数据结构也是MAPKJob状态,Vjob对象。

public voidjobAdded(JobInProgress job) {

    jobQueue.put(newJobSchedulingInfo(job.getStatus()), job);

  }

 

 EagerTaskInitializationListener

 EagerTaskInitializationListener类主要是当job加入时,对job进行初始化工作。在start()方法中启动了一个初始化job的守护线程。

线程的处理逻辑如下:对之前的jobInitQueue队列中的job执行初始化。

  public void start() throws IOException {

    this.jobInitManagerThread = new Thread(jobInitManager, "jobInitManager");

    jobInitManagerThread.setDaemon(true);

    this.jobInitManagerThread.start();

  }

该守护线程主要完成job的实始化工作,依次从队列中取出job,进行初始化。这里利用一个线程对job进行初始化,采用了线程池来完成多个job的初始化。

但是在InitJob中的线程对象调用了JobtrackerinitJob()方法。

class JobInitManager implements Runnable {

  

    public void run() {

      JobInProgress job = null;

      while (true) {

        try {

          synchronized (jobInitQueue) {

            while (jobInitQueue.isEmpty()) {

              jobInitQueue.wait();

            }

            job = jobInitQueue.remove(0);

          }

          threadPool.execute(new InitJob(job));

        } catch (InterruptedException t) {

          LOG.info("JobInitManagerThread interrupted.");

          break;

        }

      }

      LOG.info("Shutting down thread pool");

      threadPool.shutdownNow();

    }

  }

下面回到addjob()方法,此方法如下:

  public voidjobAdded(JobInProgress job) {

    synchronized (jobInitQueue) {

      jobInitQueue.add(job);

     resortInitQueue();

      jobInitQueue.notifyAll();

    }

  }

同样要将job加入到jobInitQueue队列中。同时计算队列中的job的时间优先,将先来的job放到队列前面。

 

未完,接下来的内容是TT与JT之间的心跳处理以及其他的job调度算法,如常用的fair schedule。

后续的内容还有TT进程分析以及HIVE各个操作的分析等。

原创粉丝点击