Hadoop源码分析(二)

本文详细分析了Hadoop MapReduce的Job类,包括getInstance()、set方法、waitForCompletion()等核心方法,探讨了作业提交、状态检查、任务报告获取等流程。通过对源码的解读,加深了对Job类的理解,为后续Hadoop学习打下基础。

2021SC@SDUSC

上周我们分析了org.apache.hadoop.mapreduce.Job中的的部分代码,本周将继续研究Job类中的剩余代码。

在这里插入图片描述
上图是apache官方api对class Job的描述,即Job类是作业提交者对作业的视图。它允许用户配置作业、提交作业、控制作业的执行和查询状态。set方法只能在作业被提交后生效,之后它们将抛出一个IllegalStateException。通常情况下,用户创建应用程序,通过job描述作业的各个方面,然后提交作业并监视其进度。

官方为我们提供了一个Job类的实例,展示了如何提交一个作业。

Job类实例

 	// Create a new Job
     Job job = Job.getInstance();
     job.setJarByClass(MyJob.class);
     
     // Specify various job-specific parameters     
     job.setJobName("myjob");
     
     job.setInputPath(new Path("in"));
     job.setOutputPath(new Path("out"));
     
     job.setMapperClass(MyJob.MyMapper.class);
     job.setReducerClass(MyJob.MyReducer.class);

     // Submit the job, then poll for progress until the job is complete
     job.waitForCompletion(true);

我们首先分析这段简短的代码。
首先是对job对象初始化。根据上周编写的源码分析(一),我们已经得知getInstance()是job提供的工厂方法,能够创建一个没有特定集群的新作业,将会使用通用配置创建集群。在Java doc中,对于这个function的注释是:Set the Jar by finding where a given class came from,即通过查找给定类的来源来设置Jar。
接着是设置job的相关变量,包括作业名称,输入输出路径,mapper和reducer对应的类。
最后一行涉及了waitForCompletion()方法,其源码如下:

方法waitForCompletion

/**
   * Submit the job to the cluster and wait for it to finish.
   * @param verbose print the progress to the user
   * @return true if the job succeeded
   * @throws IOException thrown if the communication with the 
   *         <code>JobTracker</code> is lost
   */
  public boolean waitForCompletion(boolean verbose
                                   ) throws IOException, InterruptedException,
                                            ClassNotFoundException {
    if (state == JobState.DEFINE) {
      submit();
    }
    if (verbose) {
      monitorAndPrintJob();
    } else {
      // get the completion poll interval from the client.
      int completionPollIntervalMillis = 
        Job.getCompletionPollInterval(cluster.getConf());
      while (!isComplete()) {
        try {
          Thread.sleep(completionPollIntervalMillis);
        } catch (InterruptedException ie) {
        }
      }
    }
    return isSuccessful();
  }

该方法会轮询进度,直到作业完成,最终提交作业。
waitForCompletion函数会提交Job到对应的Cluster,并等待Job执行结束。函数的boolean参数verbose表示是否打印Job执行的相关信息。返回的结果是一个boolean变量,用来标识Job的执行结果。

至此完成了一个完整的作业流程。

接着我们继续探索Job类中的其他方法。

方法ensureState()

private void ensureState(JobState state) throws IllegalStateException {
    if (state != this.state) {
      throw new IllegalStateException("Job in state "+ this.state + 
                                      " instead of " + state);
    }

    if (state == JobState.RUNNING && cluster == null) {
      throw new IllegalStateException
        ("Job in state " + this.state
         + ", but it isn't attached to any job tracker!");
    }
  }

首先看方法传入的参数,参数类型为JobState,进一步查看源码可知state有两种状态,即DEFINE和RUNNING。因此Job要么在定义中,要么正在运行。若作业状态变化或作业处于RUNNING状态但没有绑定集群,则会打印提示。

public enum JobState {DEFINE, RUNNING};

方法ensureFreshStatus

/**
   * Some methods rely on having a recent job status object.  Refresh
   * it, if necessary
   */
  synchronized void ensureFreshStatus() 
      throws IOException {
    if (System.currentTimeMillis() - statustime > MAX_JOBSTATUS_AGE) {
      updateStatus();
    }
  }

该方法与上方的ensureState相关,会根据设置的MAX_JOBSTATUS_AGE来判断是否要刷新作业状态,若大于设定时间则刷新。

方法getTaskReports

/**
   * Get the information of the current state of the tasks of a job.
   * 
   * @param type Type of the task
   * @return the list of all of the map tips.
   * @throws IOException
   */
  public TaskReport[] getTaskReports(TaskType type) 
      throws IOException, InterruptedException {
    ensureState(JobState.RUNNING);
    final TaskType tmpType = type;
    return ugi.doAs(new PrivilegedExceptionAction<TaskReport[]>() {
      public TaskReport[] run() throws IOException, InterruptedException {
        return cluster.getClient().getTaskReports(getJobID(), tmpType);
      }
    });
  }

我们再从网上查阅资料,得到了该方法在api中的注释:
Get the information of the current state of the tasks of a job.
Parameters:
type - Type of the task
Returns:
the list of all of the map tips.
Throws:
IOException
InterruptedException
显而易见,该方法适用于返回当前任务的报告,返回类型为TaskReport的数组,那么TaskReport拥有什么属性呢?我们点开该类进一步查看:
在这里插入图片描述
TaskReport拥有当前的任务id,所属进程,状态,诊断内容,开始与结束时间等一系列属性。通过该数组,我们可以得到当前作业的某一任务的详细信息。

方法submit

/**
   * Submit the job to the cluster and return immediately.
   * @throws IOException
   */
  public void submit() 
         throws IOException, InterruptedException, ClassNotFoundException {
    ensureState(JobState.DEFINE);
    setUseNewAPI();
    connect();
    final JobSubmitter submitter = 
        getJobSubmitter(cluster.getFileSystem(), cluster.getClient());
    status = ugi.doAs(new PrivilegedExceptionAction<JobStatus>() {
      public JobStatus run() throws IOException, InterruptedException, 
      ClassNotFoundException {
        return submitter.submitJobInternal(Job.this, cluster);
      }
    });
    state = JobState.RUNNING;
    LOG.info("The url to track the job: " + getTrackingURL());
   }

该方法在官方api的解释如下:
Submit the job to the cluster and return immediately.
Throws:
IOException
InterruptedException
ClassNotFoundException
即向集群提交作业并立即返回。submit函数会把Job提交给对应的Cluster,然后不等待Job执行结束就立刻返回。同时会把Job实例的状态设置为JobState.RUNNING,从而来表示Job正在进行中。然后在Job运行过程中,可以调用getJobState()来获取Job的运行状态。

小结

本周我进一步了解了mapreduce中的核心类Job中的相关源码,对其使用以及核心的方法有了进一步的了解,逐步向hadoop的核心前进,希望下周会有更多收获。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值