MapReduce job在JobTracker初始化源码级分析
mapreduce job提交流程源码级分析(三)中已经说明用户最终调用JobTracker.submitJob方法来向JobTracker提交作业。而这个方法的核心提交方法是JobTracker.addJob(JobID jobId, JobInProgress job)方法,这个addJob方法会把Job提交到调度器(默认是JobQueueTaskScheduler)的监听器JobQueueJobInProgressListener和EagerTaskInitializationListener(本文只讨论默认调度器)中,使用方法jobAdded(JobInProgress job),JobQueueJobInProgressListener任务是监控各个JobInProcess生命周期中的变化;EagerTaskInitializationListener是发现有新Job后对其初始化的。
一、JobQueueJobInProgressListener.jobAdded(JobInProgress job)方法。就一句代码jobQueue.put(new JobSchedulingInfo(job.getStatus()), job),先构建一个JobSchedulingInfo对象,然后和JobInProgress对应起来放入jobQueue中。JobSchedulingInfo类维护这调度这个job必备的一些信息,比如优先级(默认是NORMAL)、JobID以及开始时间startTime。
二、EagerTaskInitializationListener.jobAdded(JobInProgress job)方法。
/**
* We add the JIP to the jobInitQueue, which is processed
* asynchronously to handle split-computation and build up
* the right TaskTracker/Block mapping.
*/
@Override
public void jobAdded(JobInProgress job) {
synchronized (jobInitQueue) {
jobInitQueue.add(job); //添加进List<JobInProgress> jobInitQueue
resortInitQueue();
jobInitQueue.notifyAll(); //唤醒阻塞的进程
} }
上面方法中resortInitQueue()方法主要是对jobInitQueue中JobInProcess进行排序,先按照优先级排序,相同的再按开始时间。EagerTaskInitializationListener.start()在调度器初始化时JobQueueTaskScheduler.start()就调用了,所以先于jobAdded方法调用。EagerTaskInitializationListener.start()代码如下:
public void start() throws IOException {
this.jobInitManagerThread = new Thread(jobInitManager, "jobInitManager");
jobInitManagerThread.setDaemon(true);
this.jobInitManagerThread.start();
}
start()方法会启动一个线程:JobInitManager。
/////////////////////////////////////////////////////////////////
// Used to init new jobs that have just been created
/////////////////////////////////////////////////////////////////
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();
}
} class InitJob implements Runnable { private JobInProgress job; public InitJob(JobInProgress job) {
this.job = job;
} public void run() {
ttm.initJob(job);//对应JobTracker的对应方法
}
}
JobInitManager线程的run方法是一个死循环始终监控jobInitQueue是否为空,不为空的话就取出0位置的JobInProgress,在InitJob线程中初始化:TaskTrackerManager.initJob(job)对应JobTracker的initJob方法。这里为什么会另起线程来初始化Job呢?原因很简单,就是可能jobInitQueue中同时会有很多JobInProgress,一个一个的初始化会比较慢,所以采用多线程的方式初始化。来看initJob方法的代码:
public void initJob(JobInProgress job) {
if (null == job) {
LOG.info("Init on null job is not valid");
return;
}
try {
JobStatus prevStatus = (JobStatus)job.getStatus().clone();
LOG.info("Initializing " + job.getJobID());
job.initTasks(); //调用该实例的initTasks方 法,对job进行初始化
// Inform the listeners if the job state has changed
// Note : that the job will be in PREP state.
JobStatus newStatus = (JobStatus)job.getStatus().clone();
if (prevStatus.getRunState() != newStatus.getRunState()) {
JobStatusChangeEvent event =
new JobStatusChangeEvent(job, EventType.RUN_STATE_CHANGED, prevStatus,
newStatus);
synchronized (JobTracker.this) {
updateJobInProgressListeners(event);
}
}
} catch (KillInterruptedException kie) {
// If job was killed during initialization, job state will be KILLED
LOG.error("Job initialization interrupted:\n" +
StringUtils.stringifyException(kie));
killJob(job);
} catch (Throwable t) {
String failureInfo =
"Job initialization failed:\n" + StringUtils.stringifyException(t);
// If the job initialization is failed, job state will be FAILED
LOG.error(failureInfo);
job.getStatus().setFailureInfo(failureInfo);
failJob(job);
}
}
首先是获取初始化前的状态prevStatus;然后是job.initTasks()初始化;在获取初始化的后的状态newStatus;
job.initTasks()方法代码比较多,主要的工作是检查之后获取输入数据的分片信息TaskSplitMetaInfo[] splits = createSplits(jobId)这是去读的上传到HDFS中的文件job.splitmetainfo和job.split,要确保numMapTasks == splits.length,然后构建numMapTasks个TaskInProgress作为MapTask,
MapReduce job在JobTracker初始化源码级分析的更多相关文章
- MapReduce的ReduceTask任务的运行源码级分析
MapReduce的MapTask任务的运行源码级分析 这篇文章好不容易恢复了...谢天谢地...这篇文章讲了MapTask的执行流程.咱们这一节讲解ReduceTask的执行流程.ReduceTas ...
- MapReduce的MapTask任务的运行源码级分析
TaskTracker任务初始化及启动task源码级分析 这篇文章中分析了任务的启动,每个task都会使用一个进程占用一个JVM来执行,org.apache.hadoop.mapred.Child方法 ...
- TaskTracker任务初始化及启动task源码级分析
在监听器初始化Job.JobTracker相应TaskTracker心跳.调度器分配task源码级分析中我们分析的Tasktracker发送心跳的机制,这一节我们分析TaskTracker接受JobT ...
- 监听器初始化Job、JobTracker相应TaskTracker心跳、调度器分配task源码级分析
JobTracker和TaskTracker分别启动之后(JobTracker启动流程源码级分析,TaskTracker启动过程源码级分析),taskTracker会通过心跳与JobTracker通信 ...
- TableInputFormat分片及分片数据读取源码级分析
我们在MapReduce中TextInputFormat分片和读取分片数据源码级分析 这篇中以TextInputFormat为例讲解了InputFormat的分片过程以及RecordReader读取分 ...
- Shell主要逻辑源码级分析(1)——SHELL运行流程
版权声明:本文由李航原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/109 来源:腾云阁 https://www.qclou ...
- Flume-NG内置计数器(监控)源码级分析
Flume的内置监控怎么整?这个问题有很多人问.目前了解到的信息是可以使用Cloudera Manager.Ganglia有图形的监控工具,以及从浏览器获取json串,或者自定义向其他监控系统汇报信息 ...
- 源码级分析Android系统启动流程
首先看一下Android系统的体系结构,相信大家都不陌生 1.首先Bootloader引导程序启动完Linux内核后,会加载各种驱动和数据结构,当有了驱动以后,开始启动Android系统,同时会加载用 ...
- Shell主要逻辑源码级分析 (2)——SHELL作业控制
版权声明:本文由李航原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/110 来源:腾云阁 https://www.qclou ...
随机推荐
- android studio 运行是,app标题栏不显示
解决办法:让所有的活动都继承 AppCompatActivity就行了,如: public class FirstActivity extends AppCompatActivity{ ... }
- 手动爬虫之糗事百科(ptyhon3)
一.调用封装的Url_ProxyHelper类,源码如下 import urllib.request as ur class Url_ProxyHelper: def __init__(self, u ...
- js处理事件冒泡
给Dom元素添加事件时,有时候会遇到事件冒泡,处理方法如下: $("#Tab1 .close").live("click", function (event) ...
- Es 中一个分片一般设置多大
百度Elasticsearch-产品描述-介绍-百度云 https://cloud.baidu.com/doc/BES/FAQ.html#.2C.BB.93.08.C9.7E.2F.A3.E7.35. ...
- use getters and setters Learning PHP Design Patterns
w Learning PHP Design Patterns Much of what passes as OOP misuses getters and setters, and making ac ...
- js function,prototype,sub.
Ojbect 和Function 与普通函数和实例对象 1.实例对象的proto 指向构造函数的原型对象 2.实例对象的proto 指向Ojbect的原型 3.所有函数的proto 都指向Functi ...
- 如何理解Nginx, WSGI, Flask之间的关系
概览 之前对 Nginx,WSGI(或者 uWSGI,uwsgi),Flask(或者 Django),这几者的关系一存存在疑惑.通过查阅了些资料,总算把它们的关系理清了. 总括来说,客户端从发送一个 ...
- ES6通过Set数组去重
一.Set 1.定义 Set对象是ES6中新定义的数据结构,类似于数组,它允许你存储任何类型的唯一值,不管是原始值还是对象引用. 2.语法 new Set([iterable]) iterable:可 ...
- oracle Dba之路
如何快速的成为一个合格的 DBA? 2010年11月03日 11:25:00 阅读数:584 原文来自:http://topic.csdn.net/u/20101031/21/A78B2EA1-6F2 ...
- Mac 启动和关闭rabbitmq
1.安装 brew install rabbitmq 2.启动及关闭RabbitMQ服务 前台启动 sudo ./rabbitmq-server 或 sudo su/usr/local/Cell ...