Hadoop框架--Job提交流程--本地模式

1.job.waitForCompletion(true);

 /**
 * 主要是將任務提交到集羣中去並等待完成
 * boolean verbose:是否將進度打印給用戶看
 * return 任務成功返回true
 */
public boolean waitForCompletion(boolean verbose
                                   ) throws IOException, InterruptedException,
                                            ClassNotFoundException {
   
   
    //判斷job狀態是否爲define,避免二次提交,JobState爲枚舉:DEFINE,RUNNING
    if (state == JobState.DEFINE) {
   
   
      submit();//將任務提交到集羣 --> 1.1 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();
  }

1.1submit()

public void submit() 
       throws IOException, InterruptedException, ClassNotFoundException {
   
   
  ensureState(JobState.DEFINE);
  // 該方法做了系統兼容,避免出現框架更新,老版本無法使用
  setUseNewAPI();
  // 這裏面創建了一個很重要的對象,用於建立連接本地還是集羣連接 --> 1.1.1 connect()
  connect();
  final JobSubmitter submitter = 
      getJobSubmitter(cluster.getFileSystem(), cluster.getClient());
  status = ugi.doAs(new PrivilegedExceptionAction<JobStatus>() {
   
   
    public JobStatus run() throws IOException, InterruptedException, 
    ClassNotFoundException {
   
   
      
        /* 真正開始提交job流程,準備工作終於做完了 --> JobStatus submitJobInternal(Job job, 	            Cluster cluster)
      	*/
      
        return submitter.submitJobInternal(Job.this, cluster);
    }
  });
  state = JobState.RUNNING;
  LOG.info("The url to track the job: " + getTrackingURL());
 }

1.1.1 connect

private synchronized void connect()
          throws IOException, InterruptedException, ClassNotFoundException {
   
   
    //第一次連接的話一定爲null
    if (cluster == null) {
   
   
      cluster = 
        ugi.doAs(new PrivilegedExceptionAction<Cluster>() {
   
   
                   public Cluster run()
                          throws IOException, InterruptedException, 
                                 ClassNotFoundException {
   
   
                     //創建提交Job的代理 --> cluster(Configuration conf)
                     return new Cluster(getConfiguration());
                   }
                 });
    }
  }

 /**
 * public Cluster(Configuration conf)
 * 主要作用是獲取你在Driver中Configuration配置的文件信息,沒有配置使用默認
 */

public Cluster(Configuration conf) throws IOException {
   
   
    this(null, conf);
  }

 /**
 * 調用initialize(jobTrackAddr, conf)返回的值
 * jobTrackAddr:local還是yarn
 * conf:配置的信息
 */

public Cluster(InetSocketAddress jobTrackAddr, Configuration conf) 
      throws IOException {
   
   
    this.conf = conf;
    this.ugi = UserGroupInformation.getCurrentUser();
    initialize(jobTrackAddr, conf); // --> initialize()
  }

 /**
 * ...表示該方法中的校驗代碼
 * jobTrackAddr:狀態
 * conf:配置信息
 */

private void initialize(InetSocketAddress jobTrackAddr, Configuration conf)throws IOException {
   
   
    ...
    /*
    	判斷Driver裏配置狀態,如果是yarn則返回YarnRunner對象,如果沒有配置則返回LocalJobRunner對象
    */
    if (jobTrackAddr == null) {
   
   
        /*
          第一次判斷--> public ClientProtocol create(Configuration conf)
          第二次判斷--> public ClientProtocol create(Configuration conf)
        */
          clientProtocol = provider.create(conf);
        } else {
   
   
          clientProtocol = provider.create(jobTrackAddr, conf);
        }
    ...
}

 /**
 * yarn是否和Driver中配置的conf.set("mapreduce.framework.name","yarn");
 * 相同,相同的話就返回一個YARNRunner對象,沒有配置的話就返回一個null,而後進行
 * 第二次判斷
 */
public ClientProtocol create(Configuration conf) throws IOException {
   
   
        return "yarn".equals(conf.get("mapreduce.framework.name")) ? 
            new YARNRunner(conf) : null;
    }

 /**
 * 之前返回爲null的話就進行第二次判斷
 */

public ClientProtocol create(Configuration conf) throws IOException {
   
   
    /*
    MRConfig.FRAMEWORK_NAME:"mapreduce.framework.name"
    LOCAL_FRAMEWORK_NAME:"local"
    沒有這個值就獲得一個LOCAL_FRAMEWORK_NAME
    */
    String framework =conf.get(MRConfig.FRAMEWORK_NAME,	 MRConfig.LOCAL_FRAMEWORK_NAME);
    //判斷兩方是否都爲local,相同的話就創建LocalJobRunner()對象
    if (!MRConfig.LOCAL_FRAMEWORK_NAME.equals(framework)) {
   
   
      return null;
    }
    conf.setInt(JobContext.NUM_MAPS, 1);

    return new LocalJobRunner(conf);
  }	//	--> submint() --> return submitter.submitJobInternal(Job.this, cluster);

總結:connect方法最終要的地方就是,爲我們創建了一個關鍵的對象LocalJobRunner對象,這個對象爲我們之後提交作業所用,很重要。

1.1.2 提交JOB

JobStatus submitJobInternal(Job job, Cluster cluster)throws ClassNotFoundException, 		InterruptedException, IOException {
   
   
    
    /*
    校驗文件輸出路徑是否在Driver中配置,如果沒有配置拋出InvalidJobConfException,如果文件路徑存在拋出	   FileAlreadyException
    */
    
    checkSpecs(job);
    
    // 獲取conf配置
    
    Configuration conf = job.getConfiguration();
    addMRFrameworkToDistributedCache(conf);
	
    // 創建路徑,往路勁裏生成信息,提供給APPMaster使用 在集羣中也就是tem路勁
    
    Path jobStagingArea = JobSubmissionFiles.getStagingDir(cluster, conf);
    
    // 配置校驗信息我就用...代替了,太多容易把眼睛看花,感興趣的朋友可以用DeBug邊跳邊看裏面的具體信息。
    		
    ...
    
    // 創建jobId 也就是8088端口中 任務的id
    JobID jobId = submitClient.getNewJobID();
    // 獲得jobId設置到job裏
    job.setJobID(jobId);
    // 將jobStagingArea和jobId拼在一起,拼成一個提交信息(配置信息,切片信息,jar包)的路徑
	Path submitJobDir = new Path(jobStagingArea, jobId.toString());
    	
    ...
    // 拷貝jar包到集羣(本地模式看不到,在向集羣提交的時候才能看到jar包)
    copyAndConfigureFiles(job, submitJobDir);
    // 會在submitJobDir目錄下創建一個job.xml文件
    Path submitJobFile = JobSubmissionFiles.getJobConfPath(submitJobDir);
    LOG.debug("Creating splits at " + jtFs.makeQualified(submitJobDir));
    /* 切片,具體怎麼切,再看切片源碼的時候會提到,在執行完該方法後submitJobDir路徑中會多出split和crc	文件
    */
    int maps = writeSplits(job, submitJobDir);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章