一、概要描述

上一篇博文中主要描述了JobTracker接收作业的几个服务(或功能)模块的初始化过程。本节将介绍这些服务(或功能)是如何接收到提交的job。本来作业的初始化也可以在本节内描述,但是涉及到JobInProgress的初始化过程放在一张图上太拥挤,就分开到下一篇文章中描述。

二、 流程描述  

1. JobClient通过RPC的方式向JobTracker提交作业

2. 调用JobTracker的submitJob方法。该方法是JobTracker向外提供的供调用的提交作业的接口。

3. submit方法中调用JobTracker的addJob方法。

4. 在addJob方法中会把作业加入到集合中供调度,并会触发注册的JobInProgressListener的jobAdded事件。由上篇博文的jobtracker相关服务和功能的初始化的FairScheduler的start方法中看到,这里注册的是两个JobInProgressListener。分别是FairScheduler的内部类JobListener和EagerTaskInitializationListener

5. FairScheduler的内部类JobListener响应jobAdded事件事件

6. EagerTaskInitializationListener响应jobAdded事件事件

三、代码详细

 1. JobClient的submitJob方法,调用submitJobInternal方法。

主要流程:

1)通过调用JobTracker的getNewJobId()向jobtracker请求一个新的作业ID
2)获取job的jar、输入分片、作业描述等几个路径信息,以jobId命名。
3)其中getSystemDir()是返回jobtracker的系统目录,来放置job相关的文件。包括:mapreduce的jar文件submitJarFile、分片文件submitSplitFile、作业描述文件submitJobFile
4)检查作业的输出说明,如果没有指定输出目录或输出目录以及存在,则作业不提交。参照org.apache.hadoop.mapreduce.lib.output.FileOutputFormatcheckOutputSpecs方法。如果没有指定,则抛出InvalidJobConfException,文件已经存在则抛出FileAlreadyExistsException
5)计算作业的输入分片。通过InputFormat的getSplits(job)方法获得作业的split并将split序列化封装为RawSplit。返回split数目,也即代表有多个分片有多少个map。详细参见InputFormat获取Split的方法。
6)writeNewSplits 方法把输入分片写到JobTracker的job目录下。
7)将运行作业所需的资源(包括作业jar文件,配置文件和计算所得的输入分片)复制到jobtracker的文件系统中一个以作业ID命名的目录下。
8)使用句柄JobSubmissionProtocol通过RPC远程调用的submitJob()方法,向JobTracker提交作业。JobTracker作业放入到内存队列中,由作业调度器进行调度。并初始化作业实例。JobTracker创建job成功后会给JobClient传回一个JobStatus对象 用于记录job的状态信息,如执行时间、Map和Reduce任务完成的比例等。JobClient会根据这个JobStatus对象创建一个 NetworkedJob的RunningJob对象,用于定时从JobTracker获得执行过程的统计数据来监控并打印到用户的控制台。

1 public RunningJob submitJobInternal(JobConf job)
2 throws FileNotFoundException, ClassNotFoundException,
3 InterruptedException, IOException {
4
5 // 1)通过调用JobTracker的getNewJobId()向jobtracker请求一个新的作业ID
6 JobID jobId = jobSubmitClient.getNewJobId();
7 // 2)获取job的jar、输入分片、作业描述等几个路径信息,以jobId命名。
8 // 3)其中getSystemDir()是返回jobtracker的系统目录,来放置job相关的文件。包括:mapreduce的jar文件submitJarFile、分片文件submitSplitFile、作业描述文件submitJobFile
9
10 Path submitJobDir = new Path(getSystemDir(), jobId.toString());
11 Path submitJarFile = new Path(submitJobDir, "job.jar");
12 Path submitSplitFile = new Path(submitJobDir, "job.split");
13 configureCommandLineOptions(job, submitJobDir, submitJarFile);
14 Path submitJobFile = new Path(submitJobDir, "job.xml");
15 int reduces = job.getNumReduceTasks();
16 JobContext context = new JobContext(job, jobId);
17
18 // Check the output specification
19 // 4)检查作业的输出说明,如果没有指定输出目录或输出目录以及存在,则作业不提交。参照org.apache.hadoop.mapreduce.lib.output.FileOutputFormat的checkOutputSpecs方法。如果没有指定,则抛出InvalidJobConfException,文件已经存在则抛出FileAlreadyExistsException
20
21 if (reduces == 0 ? job.getUseNewMapper() : job.getUseNewReducer()) {
22 org.apache.hadoop.mapreduce.OutputFormat<?, ?> output = ReflectionUtils
23 .newInstance(context.getOutputFormatClass(), job);
24 output.checkOutputSpecs(context);
25 } else {
26 job.getOutputFormat().checkOutputSpecs(fs, job);
27 }
28
29 // 5)计算作业的输入分片。详细参见FormatInputFormat获取Split的方法。
30 // 6)writeNewSplits 方法把输入分片写到JobTracker的job目录下,名称是submitSplitFile
31 // job.split名称。
32 // 7)将运行作业所需的资源(包括作业jar文件,配置文件和计算所得的输入分片)复制到jobtracker的文件系统中一个以作业ID命名的目录下。
33
34 // Create the splits for the job
35 LOG.debug("Creating splits at " + fs.makeQualified(submitSplitFile));
36 int maps;
37 if (job.getUseNewMapper()) {
38 maps = writeNewSplits(context, submitSplitFile);
39 } else {
40 maps = writeOldSplits(job, submitSplitFile);
41 }
42 job.set("mapred.job.split.file", submitSplitFile.toString());
43 job.setNumMapTasks(maps);
44
45 // Write job file to JobTracker's fs
46 FSDataOutputStream out = FileSystem.create(fs, submitJobFile,
47 new FsPermission(JOB_FILE_PERMISSION));
48
49 try {
50 job.writeXml(out);
51 } finally {
52 out.close();
53 }
54
55 // 8)使用句柄JobSubmissionProtocol通过RPC远程调用的submitJob()方法,向JobTracker提交作业。JobTracker根据接收到的submitJob()方法调用后,把调用放入到内存队列中,由作业调度器进行调度。并初始化作业实例。
56
57 JobStatus status = jobSubmitClient.submitJob(jobId);
58 if (status != null) {
59 return new NetworkedJob(status);
60 } else {
61 throw new IOException("Could not launch job");
62 }
63 }

2. JobTracker的submitJob方法,是JobTracker向外提供的供调用的提交作业的接口。

public synchronized JobStatus submitJob(JobID jobId) throws IOException {
if(jobs.containsKey(jobId)) {
//检查Job已经存在,则仅仅返回其status
return jobs.get(jobId).getStatus();
}
//不存在,则创建该job 的JobInProgress 实例,
JobInProgress job = new JobInProgress(jobId, this, this.conf);
String queue = job.getProfile().getQueueName();
new CleanupQueue().addToQueue(conf,getSystemDirectoryForJob(jobId));
}
// check for access
checkAccess(job, QueueManager.QueueOperation.SUBMIT_JOB);
// 检查内存是否够用
checkMemoryRequirements(job);
return addJob(jobId, job);
}

3.  JobTracker的addJob方法,把作业加入到集合中供调度。其中jobs 是Map<JobID, JobInProgress>类型,维护着加入进来的JobInProgress job。

private synchronized JobStatus addJob(JobID jobId, JobInProgress job) {
totalSubmissions++;
synchronized (jobs) {
synchronized (taskScheduler) {
//将job实例加入到Map<JobID, JobInProgress> jobs 集合中,
jobs.put(job.getProfile().getJobID(), job);
//并触发所有注册的JobInProgressListener,通知其一个新Job添加进来了,让各个Listener响应各自的动作。
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);
return job.getStatus();
}

4.FairScheduler.JobListener的jobAdded方法。jobAdded方法是JobInProgressListener中定义的在JobTracker中响应job变化的方法。在这个方法中,只是为每个加入的Job创建一个用于FairScheduler调度用的JobInfo对象,并将其和job的对应的存储在Map<JobInProgress, JobInfo> infos集合中。

 @Override
public void jobAdded(JobInProgress job) {
synchronized (FairScheduler.this) {
poolMgr.addJob(job);
JobInfo info = new JobInfo();
infos.put(job, info);
update();
}
}

5. EagerTaskInitializationListener的jobAdded方法。 这个方法其实在前面文章中介绍过,在EagerTaskInitializationListener中,jobAdded只是简单的把job加入到一个List<JobInProgress>类型的 jobInitQueue中。并不直接对其进行初始化,对其中的job的处理由另外线程JobInitManager来做。该线程,一直检查jobInitQueue是否有作业,有则拿出来从线程池中取一个线程InitJob处理。关于作业的初始化过程专门在下一篇文章中介绍。

@Override
public void jobAdded(JobInProgress job) {
synchronized (jobInitQueue) {
jobInitQueue.add(job);
resortInitQueue();
jobInitQueue.notifyAll();
} }

完。

为了转载内容的一致性、可追溯性和保证及时更新纠错,转载时请注明来自:http://www.cnblogs.com/douba/p/hadoop_mapreduce_jobadded.html。谢谢!

【Hadoop代码笔记】Hadoop作业提交之JobTracker接收作业提交的更多相关文章

  1. 【Hadoop代码笔记】通过JobClient对Jobtracker的调用详细了解Hadoop RPC

    Hadoop的各个服务间,客户端和服务间的交互采用RPC方式.关于这种机制介绍的资源很多,也不难理解,这里不做背景介绍.只是尝试从Jobclient向JobTracker提交作业这个最简单的客户端服务 ...

  2. 【Hadoop代码笔记】目录

    整理09年时候做的Hadoop的代码笔记. 开始. [Hadoop代码笔记]Hadoop作业提交之客户端作业提交 [Hadoop代码笔记]通过JobClient对Jobtracker的调用看详细了解H ...

  3. 【hadoop代码笔记】hadoop作业提交之汇总

    一.概述 在本篇博文中,试图通过代码了解hadoop job执行的整个流程.即用户提交的mapreduce的jar文件.输入提交到hadoop的集群,并在集群中运行.重点在代码的角度描述整个流程,有些 ...

  4. 【hadoop代码笔记】Mapreduce shuffle过程之Map输出过程

    一.概要描述 shuffle是MapReduce的一个核心过程,因此没有在前面的MapReduce作业提交的过程中描述,而是单独拿出来比较详细的描述. 根据官方的流程图示如下: 本篇文章中只是想尝试从 ...

  5. 【Hadoop代码笔记】Hadoop作业提交之JobTracker等相关功能模块初始化

    一.概要描述 本文重点描述在JobTracker一端接收作业.调度作业等几个模块的初始化工作.想过模块的介绍会在其他文章中比较详细的描述.受理作业提交在下一篇文章中会进行描述. 为了表达的尽可能清晰一 ...

  6. 【Hadoop代码笔记】Hadoop作业提交之客户端作业提交

    1.      概要描述仅仅描述向Hadoop提交作业的第一步,即调用Jobclient的submitJob方法,向Hadoop提交作业. 2.      详细描述Jobclient使用内置的JobS ...

  7. 【Hadoop代码笔记】Hadoop作业提交之TaskTracker获取Task

    一.概要描述 在上上一篇博文和上一篇博文中分别描述了jobTracker和其服务(功能)模块初始化完成后,接收JobClient提交的作业,并进行初始化.本文着重描述,JobTracker如何选择作业 ...

  8. 【Hadoop代码笔记】Hadoop作业提交之Job初始化

    一.概要描述 在上一篇博文中主要描述了JobTracker和其几个服务(或功能)模块的接收到提交的job后的一些处理.其中很重要的一部分就作业的初始化.因为代码片段图的表达问题,本应该在上篇描述的内容 ...

  9. 【hadoop代码笔记】Hadoop作业提交中EagerTaskInitializationListener的作用

    在整理FairScheduler实现的task调度逻辑时,注意到EagerTaskInitializationListener类.差不多应该是job提交相关的逻辑代码中最简单清楚的一个了. todo: ...

随机推荐

  1. Quartz的misfire特性

    Quartz的misfire特性 只有一个线程.多个job 第一个job产生misfire(executeTime>Interval) 且是repeatForever 那么只会运行第一个job, ...

  2. kali 安装中文输入法

    (1)apt-get install fcitx-googlepinyin (2)你希望继续执行吗?Y (3)连续执行数次 (4)init 6(命令行重启)

  3. PCL—低层次视觉—点云分割(基于形态学)

    1.航空测量与点云的形态学 航空测量是对地形地貌进行测量的一种高效手段.生成地形三维形貌一直是地球学,测量学的研究重点.但对于城市,森林,等独特地形来说,航空测量会受到影响.因为土地表面的树,地面上的 ...

  4. Map集合案例

    1.获取字符串中每一个字母出现的次数. 比如"aababcabcdabcde",结果为:a(5)b(4)c(3)d(2)e(1) 分析如下: package mapexercise ...

  5. Eclipse groovy in action

    Eclipse :Version: Juno Service Release 2GrEclipse plugins:http://dist.springsource.org/release/GRECL ...

  6. Segmentation Fault错误原因总结

    最近在项目上遇到了Segmentation Fault的错误,一直调试不出来是哪里出了问题,对于刚接触嵌入式的,也不知道该如何去调试一个项目,定位内存问题,纠结了好几天,好阿红整理下自己的思路.从头开 ...

  7. AXURE制作APP抽屉式菜单

    1.拖一个dynamic panel到窗体,将State1改名为State_首页: 2.拖2个dynamic panel到State_首页中,分别命名为侧边菜单及首页内容,首页内容盖住侧边菜单: 3. ...

  8. OEM - emctl resetTZ agent 设置时区

    [oracle@redhat4 config]$ cd $ORACLE_HOME/redhat4.7_orcl/sysman/config [oracle@redhat4 config]$ pwd/u ...

  9. 进程间通信的WM_COPYDATA的使用

    http://blog.csdn.net/ao929929fei/article/details/6316174 接收数据的一方 ON_WM_COPYDATA() afx_msg BOOL OnCop ...

  10. 省常中模拟 Test3 Day1

    tile 贪心 题意:给出一个矩形,用不同字母代表的正方形填充,要求相邻的方块字母不能相同,求字典序(将所有行拼接起来)最小的方案. 初步解法:一开始没怎么想,以为策略是每次填充一个尽量大的正方形.但 ...