Hadoop-1.2.1学习之Job创建和提交源码分析
在Hadoop中,MapReduce的Java作业通常由编写Mapper和Reducer開始。接着创建Job对象。然后使用该对象的set方法设置Mapper和Reducer以及诸如输入输出等參数,最后调用Job对象的waitForCompletion(true)方法提交作业并等待作业的完毕。虽然使用了寥寥数语就描写叙述了作业的创建和提交,但实际情况要复杂的多。本篇文章将通过分析源码来深入学习该过程。
通常使用public Job(Configuration conf, String jobName)创建Job作业对象,都会指定作业名称,hadoop代码仅仅是将jobName设置为參数mapred.job.name的值。
除了设置作业名称外,Job的构造函数还会使用Configuration对象初始化org.apache.hadoop.mapred.JobConf对象conf,以及使用UserGroupInformation.getCurrentUser()获取当前用户ugi。当中JobConf是描写叙述MapReduce作业的主要接口,包括设置作业名称在内的很多方法都是由该类完毕的。
UserGroupInformation类用包括了用户和组的信息。该类封装了JAAS(Java
Authentication AuthorizationService。Java认证和授权服务),并提供方法确定username和组。
当创建了Job对象后一般会设置Mapper和Reducer。比方job.setMapperClass,正像上面提到的,该操作实际是由JobConf对象完毕的,详细代码例如以下,其他的设置方法类似:
public void setMapperClass(Class<?
extends Mapper> cls) throws IllegalStateException {
ensureState(JobState.DEFINE);
conf.setClass(MAP_CLASS_ATTR, cls, Mapper.class);
}
在设置完作业运行须要的參数后。运行job.waitForCompletion(true)向集群提交作业并等待作业运行完毕。当中的boolean类型的參数用于决定是否向用户打印作业的运行进度。该方法的详细代码例如以下:
public boolean waitForCompletion(boolean verbose) throws IOException, InterruptedException,ClassNotFoundException {
if (state == JobState.DEFINE) {
submit();
}
if (verbose) {
jobClient.monitorAndPrintJob(conf, info);
} else {
info.waitForCompletion();
}
return isSuccessful();
}
当新创建一个作业时,该作业的JobState state = JobState.DEFINE,所以上面的代码中会运行submit方法。当在submit返回后会依据參数verbose为true或false运行不同的方法。如今详细submit的实现:
public void submit() throws IOException, InterruptedException, ClassNotFoundException {
ensureState(JobState.DEFINE);
setUseNewAPI();//默认使用新版本号中的API,除非显示设置了老版本号的API
// Connect to the JobTracker and submit the job
connect();
info = jobClient.submitJobInternal(conf);
super.setJobID(info.getID());
state = JobState.RUNNING;
}
在submit中,先确认Job的state为JobState.DEFINE。并最后在将作业提交后设置为JobState.RUNNING。connect方法用于打开到JobTracker的连接,该方法的代码为:
private void connect() throws IOException, InterruptedException {
ugi.doAs(new PrivilegedExceptionAction<Object>() {
public Object run() throws IOException {
jobClient = new JobClient((JobConf) getConfiguration());
return null;
}
});
}
在进一步分析之前,须要先了解两个对象。各自是JobClient jobClient和RunningJobinfo,当中jobClient是用户作业与JobTracker交互的主要接口,该类具有提交作业,跟踪作业进度,訪问任务日志和获取MapReduce集群状态信息等功能。RunningJob是接口,用于查询正在执行的MapReduce作业的细节,当调用jobClient的submitJobInternal时。返回的是jobClient的内部类NetworkedJob(该类实现了RunningJob)。在connect方法中,主要是实例化了jobClient对象,而ugi的doAs方法的返回值为run方法的返回值,后面还会使用该方法(实际情况是该方法被大量使用)。在JobClient的构造方法中,主要完毕了连接JobTracker的工作,该工作又交给了init方法,该方法的详细实现为:
public void init(JobConf conf) throws IOException {
String tracker = conf.get("mapred.job.tracker", "local");
// mapreduce.client.tasklog.timeout
tasklogtimeout = conf.getInt(
TASKLOG_PULL_TIMEOUT_KEY, DEFAULT_TASKLOG_TIMEOUT);
this.ugi = UserGroupInformation.getCurrentUser();
if ("local".equals(tracker)) {
conf.setNumMapTasks(1);
this.jobSubmitClient = new LocalJobRunner(conf);
} else {
this.rpcJobSubmitClient = createRPCProxy(JobTracker.getAddress(conf), conf);
this.jobSubmitClient = createProxy(this.rpcJobSubmitClient, conf);
}
}
在该方法中着重分析非单机模式下的情况。即mapred.job.tracker的值不是local。也即else语句中的代码。rpcJobSubmitClient和jobSubmitClient是类型为JobSubmissionProtocol的两个对象,JobClient和JobTracker使用该接口通信,JobClient使用该接口的方法提交作业及了解当前系统的状态。方法createRPCProxy和createProxy用于创建实现JobSubmissionProtocol的client对象。
在连接到JobTracker后,接着使用jobClient的submitJobInternal向JobTracker提交作业。
在该方法中首先确定存放作业文件的路径,该路径为${mapreduce.jobtracker.staging.root.dir}/{user-name}/.staging设置,若未设置mapreduce.jobtracker.staging.root.dir则使用/tmp/hadoop/mapred/staging/${user-name}/.staging。然后在上述文件夹创建名为作业Id的文件夹,并将參数mapreduce.job.dir设置为该值。即${mapreduce.jobtracker.staging.root.dir}/{user-name}/.staging/jobId,上面的文件夹均是相对于fs.default.name设置的值。接下来将作业的jar文件复制到${mapreduce.jobtracker.staging.root.dir}/{user-name}/.staging/jobId中,并重命名为job.jar文件。该工作由copyAndConfigureFiles方法完毕。接着须要在上述文件夹中创建job.xml文件。获取Reduce任务的数量,切割输入文件并依据切割所得块数设置Map任务的数量。做完上述工作后,使用以下的代码提交作业:
status = jobSubmitClient.submitJob( jobId, submitJobDir.toString(), jobCopy.getCredentials());
当将作业提交到JobTracker后。作业的运行将由JobTracker负责,而做为提交作业的client能够选择是否打印作业运行进度。
综上在Hadoop-1.2.1中作业的创建和提交包含例如以下的一些过程:
- 设置作业的输入输出參数
- 拷贝作业文件和配置文件到特定文件夹中
- 计算作业的分片并设置Map任务的数量
- 向JobTracker提交作业并可选的监控作业执行进度
Hadoop-1.2.1学习之Job创建和提交源码分析的更多相关文章
- Spring Cloud 学习 之 Spring Cloud Eureka(源码分析)
Spring Cloud 学习 之 Spring Cloud Eureka(源码分析) Spring Boot版本:2.1.4.RELEASE Spring Cloud版本:Greenwich.SR1 ...
- Buffer的创建及使用源码分析——ByteBuffer为例
目录 Buffer概述 Buffer的创建 Buffer的使用 总结 参考资料 Buffer概述 注:全文以ByteBuffer类为例说明 在Java中提供了7种类型的Buffer,每一种类型的Buf ...
- (转)Bootstrap 之 Metronic 模板的学习之路 - (2)源码分析之 head 部分
https://segmentfault.com/a/1190000006684122 下面,我们找个目录里面想对较小的文件来分析一下源码结构,我们可以看到,page_general_help.htm ...
- 并发编程学习笔记(七、Thread源码分析)
目录: 常见属性 构造函数 start() run() 常见属性: /** * 线程名称 */ private volatile String name; /** * 线程优先级 */ private ...
- [原创]java WEB学习笔记70:Struts2 学习之路-- struts2拦截器源码分析,运行流程
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- 深度学习入门-4.1 AND.py 源码分析
源代码 ------------------------------------------------------------------------------------------------ ...
- (转)Bootstrap 之 Metronic 模板的学习之路 - (4)源码分析之脚本部分
https://segmentfault.com/a/1190000006709967 上篇我们将 body 标签主体部分进行了简单总览,下面看看最后的脚本部门. 页面结尾部分(Javascripts ...
- (转)Bootstrap 之 Metronic 模板的学习之路 - (3)源码分析之 body 部分
https://segmentfault.com/a/1190000006697252 body 的组成结构 body 部分包含了 HEADER.CONTAINER.FOOTER,其中 CONTAIN ...
- Spring AOP 源码分析 - 创建代理对象
1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...
随机推荐
- poj 2912 并查集(食物链加强版)
题目:给出n个人玩剪刀石头布的游戏,其中有一个人是裁判,剩下的人分为3组,每一组的人只出某一种手型,裁判可以任意出.问是否能判断出哪个人是裁判 链接:点我 分分钟看吐血,先把食物链看懂吧 枚举裁判,然 ...
- seebug的反爬虫技术初探
1.通过request库无法直接爬取,返回521 >>> import requests >>> req = requests.get('https://www.s ...
- hdu 1565 最小割
黑白染色,源指向白,黑指向汇,容量都是方格中数的大小,相邻的格子白指向黑,容量为oo,然后求一次最小割. 这个割是一个简单割,如果只选择不在割中的点,那么一种割就和一个选数方案一一对应,割的大小就是不 ...
- bzoj 4780: [Usaco2017 Open]Modern Art 2
4780: [Usaco2017 Open]Modern Art 2 Time Limit: 10 Sec Memory Limit: 128 MB Description Having becom ...
- 原生+H5开发之:js交互【location方式】
1. 交互方式总结 1Android与JS通过WebView互相调用方法,实际上是: Android去调用JS的代码 JS去调用Android的代码 二者沟通的桥梁是WebView 对于Android ...
- 要使用C#实现一个ActiveX控件
要使用C#实现一个ActiveX控件,需要解决三个问题: 1.使.NET组件能够被COM调用 2.在客户机上注册后,ActiveX控件能通过IE的安全认证 3.未在客户机上注册时,安装包能通过IE的签 ...
- linux上SVN解决冲突的办法
转载:http://www.aixchina.net/club/thread-25902-1-1.html 这里,先说说冲突解决. 怎么会发生冲突呢? 两个人修改了不同文件?不会有冲突,他们不相关. ...
- 从Log4j迁移到LogBack的理由
英文原文:Reasons to prefer logback over log4j 无论从设计上还是实现上,Logback相对log4j而言有了相对多的改进.不过尽管难以一一细数,这里还是列举部分理由 ...
- 2014 百度之星 题解 1004 Labyrinth
Problem Description 度度熊是一仅仅喜欢探险的熊,一次偶然落进了一个m*n矩阵的迷宫,该迷宫仅仅能从矩阵左上角第一个方格開始走,仅仅有走到右上角的第一个格子才算走出迷宫,每一次仅仅能 ...
- Linux进程间通信:管道,信号量,消息队列,信号,共享内存,套接字
Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...