转自:http://blog.csdn.net/jaytalent?viewmode=contents

MapReduce调度与执行原理系列文章

一、MapReduce调度与执行原理之作业提交

二、MapReduce调度与执行原理之作业初始化

三、MapReduce调度与执行原理之任务调度

四、MapReduce调度与执行原理之任务调度(续)

前言:本文旨在理清在Hadoop中一个MapReduce作业(Job)在提交到框架后的整个生命周期过程,权作总结和日后参考,如有问题,请不吝赐教。本文不涉及Hadoop的架构设计,如有兴趣请参考相关书籍和文献。在梳理过程中,我对一些感兴趣的源码也会逐行研究学习,以期强化基础。
作者:Jaytalent
开始日期:2013年9月9日

参考资料:【1】《Hadoop技术内幕--深入解析MapReduce架构设计与实现原理》董西成
                  【2】Hadoop 1.0.0 源码
                            【3】《Hadoop技术内幕--深入解析Hadoop Common和HDFS架构设计与实现原理》蔡斌 陈湘萍
一个MapReduce作业的生命周期大体分为5个阶段【1】:
1. 作业提交与初始化
2. 任务调度与监控
3. 任务运行环境准备
4. 任务执行
5. 作业完成
现逐一学习。
由于作业提交是在客户端完成,而初始化在JobTracker完成,本文只关注前者,后者留待下一篇文章学习研究。
一、作业提交与初始化
以WordCount作业为例,先看作业提交的代码片段:
  1. Job job = new Job(conf, "word count");
  2. job.setJarByClass(WordCount.class);
  3. job.setMapperClass(TokenizerMapper.class);
  4. job.setCombinerClass(IntSumReducer.class);
  5. job.setReducerClass(IntSumReducer.class);
  6. job.setOutputKeyClass(Text.class);
  7. job.setOutputValueClass(IntWritable.class);
  8. FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
  9. FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
  10. System.exit(job.waitForCompletion(true) ? 0 : 1);
这里使用的新的MapReduce API。job.waitForCompletion(true)函数调用开始作业提交过程。接下来,依次调用:job.submit --> JobClient.submitJobInternal方法,真正实现作业提交。在JobClient.submitJobInternal方法中,主要有以下准备工作:
1. 获取作业ID
  1. JobID jobId = jobSubmitClient.getNewJobId();

作业ID时从JobTracker获取的,这是一次RPC调用,方法为getNewJobId,定义在JobSubmissionProtocol接口。

  1. private JobSubmissionProtocol jobSubmitClient;
Hadoop的RPC机制是基于动态代理实现的。客户端代码使用RPC类提供的代理对象调用服务器的方法。MapReduce中定义了一系列协议接口用于RPC通信。这些协议包括:
a. JobSubmissionProtocol
b. RefreshUserMappingsProtocol
c. RefreshAuthorizationPolicyProtocol
d. AdminOperationsProtocol
e. InterTrackerProtocol
f. TaskUmbilicalProtocol
前面四个协议用于客户端,最后两个协议位于MapReduce内部。这里使用的getNewJobId方法即协议JobSubmissionProtocol所定义:
  1. /**
  2. * Allocate a name for the job.
  3. * @return a unique job name for submitting jobs.
  4. * @throws IOException
  5. */
  6. public JobID getNewJobId() throws IOException;

用户使用该协议通过JobTracker提交作业,查看作业状态等。

2. 作业文件上传
JobClient会根据作业配置信息将作业所需文件上传到JobTracker的文件系统,通常是HDFS。配置信息由JobConf类对象维护。在新的API中,JobConf对象作为JobContext对象的组成部分,作业类Job即继承于JobContext类。
在上传文件前,需要在HDFS上创建必要的目录。上传文件的具体过程从JobClient.submitJobInternal方法中这句调用开始:
  1. copyAndConfigureFiles(jobCopy, submitJobDir);

在配置了提交副本数(mapred.submit.replication,默认为10)等信息后,主要代码分析如下(为了清晰起见,省略了一些日志和异常处理):

  1. // Retrieve command line arguments placed into the JobConf
  2. // by GenericOptionsParser.
  3. String files = job.get("tmpfiles");
  4. String libjars = job.get("tmpjars");
  5. String archives = job.get("tmparchives");

首先,从配置中获取不同类型文件的名称和路径,这些配置在作业提交时从命令行(Hadoop Shell)指定。files表示作业依赖的普通文件,比如文本文件;libjars表示应用程序依赖的第三方jar包;archives表示应用程序使用的多个文件打包而成的压缩文件。

  1. // Create a number of filenames in the JobTracker's fs namespace
  2. FileSystem fs = submitJobDir.getFileSystem(job);
  3. submitJobDir = fs.makeQualified(submitJobDir);
  4. FsPermission mapredSysPerms = new FsPermission(JobSubmissionFiles.JOB_DIR_PERMISSION);
  5. FileSystem.mkdirs(fs, submitJobDir, mapredSysPerms);
  6. Path filesDir = JobSubmissionFiles.getJobDistCacheFiles(submitJobDir);
  7. Path archivesDir = JobSubmissionFiles.getJobDistCacheArchives(submitJobDir);
  8. Path libjarsDir = JobSubmissionFiles.getJobDistCacheLibjars(submitJobDir);

接下来,在JobTracker的文件系统(通常为HDFS)的命名空间创建一系列文件路径名,其中包括前述三种文件类型。
有了路径名后,在HDFS上创建路径并将这些文件拷贝到对应的目录中,代码如下:

  1. // add all the command line files/ jars and archive
  2. // first copy them to jobtrackers filesystem
  3. if (files != null) {
  4. FileSystem.mkdirs(fs, filesDir, mapredSysPerms);
  5. String[] fileArr = files.split(",");
  6. for (String tmpFile: fileArr) {
  7. URI tmpURI;
  8. tmpURI = new URI(tmpFile);
  9. Path tmp = new Path(tmpURI);
  10. Path newPath = copyRemoteFiles(fs,filesDir, tmp, job, replication);
  11. URI pathURI = getPathURI(newPath, tmpURI.getFragment());
  12. DistributedCache.addCacheFile(pathURI, job);
  13. DistributedCache.createSymlink(job);
  14. }
  15. }
  16. if (libjars != null) {
  17. FileSystem.mkdirs(fs, libjarsDir, mapredSysPerms);
  18. String[] libjarsArr = libjars.split(",");
  19. for (String tmpjars: libjarsArr) {
  20. Path tmp = new Path(tmpjars);
  21. Path newPath = copyRemoteFiles(fs, libjarsDir, tmp, job, replication);
  22. DistributedCache.addArchiveToClassPath
  23. (new Path(newPath.toUri().getPath()), job, fs);
  24. }
  25. }
  26. if (archives != null) {
  27. FileSystem.mkdirs(fs, archivesDir, mapredSysPerms);
  28. String[] archivesArr = archives.split(",");
  29. for (String tmpArchives: archivesArr) {
  30. URI tmpURI;
  31. tmpURI = new URI(tmpArchives);
  32. Path tmp = new Path(tmpURI);
  33. Path newPath = copyRemoteFiles(fs, archivesDir, tmp, job, replication);
  34. URI pathURI = getPathURI(newPath, tmpURI.getFragment());
  35. DistributedCache.addCacheArchive(pathURI, job);
  36. DistributedCache.createSymlink(job);
  37. }

注意,MapReduce作业文件的上传和下载是通过DistributedCache工具完成的,它是一个数据分发工具。用户指定的文件会被分发到各个TaskTracker上以运行Task。这里暂不涉及该工具的细节,留待日后讨论。

最后,将作业对应的jar文件拷贝到HDFS中:
  1. String originalJarPath = job.getJar();
  2. if (originalJarPath != null) {           // copy jar to JobTracker's fs
  3. // use jar name if job is not named.
  4. if ("".equals(job.getJobName())){
  5. job.setJobName(new Path(originalJarPath).getName());
  6. }
  7. Path submitJarFile = JobSubmissionFiles.getJobJar(submitJobDir);
  8. job.setJar(submitJarFile.toString());
  9. fs.copyFromLocalFile(new Path(originalJarPath), submitJarFile);
  10. fs.setReplication(submitJarFile, replication);
  11. fs.setPermission(submitJarFile,
  12. new FsPermission(JobSubmissionFiles.JOB_FILE_PERMISSION));
  13. }

注意,在每次上传一种类型的文件后,都会将这种文件的路径配置到JobConf对象中,具体的工作由

  1. DistributedCache.addCacheFile(pathURI, job);
  2. DistributedCache.addArchiveToClassPath(new Path(newPath.toUri().getPath()), job, fs);
  3. DistributedCache.addCacheArchive(pathURI, job);
  4. job.setJar(submitJarFile.toString());

这四行代码完成。顺便提一句,Path类Hadoop文件系统在java.net.URI的基础上抽象了文件系统中的路径【3】。Java的File类和URL类分别抽象了不同的事物,Path可以说将二者统一起来。
3. 生成InputSplit文件

JobClient调用InputFormat的getSplits方法将用户提交的输入文件生成InputSplit相关信息。
  1. // Create the splits for the job
  2. FileSystem fs = submitJobDir.getFileSystem(jobCopy);
  3. int maps = writeSplits(context, submitJobDir);
  4. jobCopy.setNumMapTasks(maps);

jobCopy是一个JobConf对象。其中,writeSplits方法会实际调用InputSplit.getSplits方法生成splits信息,并将splits原始信息和元信息写入HDFS对应的目录和文件中。有关split的生成过程日后研究,这里不展开了。最后,将作业对应的JobConf对象以XML配置文件形式写入到HDFS中:

  1. // Write job file to JobTracker's fs
  2. FSDataOutputStream out =
  3. FileSystem.create(fs, submitJobFile,
  4. new FsPermission(JobSubmissionFiles.JOB_FILE_PERMISSION));
  5. try {
  6. jobCopy.writeXml(out);
  7. } finally {
  8. out.close();
  9. }

至此,作业文件上传才算正式完毕。
接下来,作业将被提交到JobTracker,请关注下篇文章:

MapReduce调度与执行原理系列文章的更多相关文章

  1. MapReduce调度与执行原理之任务调度

    前言 :本文旨在理清在Hadoop中一个MapReduce作业(Job)在提交到框架后的整个生命周期过程,权作总结和日后参考,如有问题,请不吝赐教.本文不涉及Hadoop的架构设计,如有兴趣请参考相关 ...

  2. MapReduce调度与执行原理之作业提交

    前言 :本文旨在理清在Hadoop中一个MapReduce作业(Job)在提交到框架后的整个生命周期过程,权作总结和日后参考,如有问题,请不吝赐教.本文不涉及Hadoop的架构设计,如有兴趣请参考相关 ...

  3. MapReduce调度与执行原理之作业初始化

    前言 :本文旨在理清在Hadoop中一个MapReduce作业(Job)在提交到框架后的整个生命周期过程,权作总结和日后参考,如有问题,请不吝赐教.本文不涉及Hadoop的架构设计,如有兴趣请参考相关 ...

  4. MapReduce调度与执行原理之任务调度(续)

    前言 :本文旨在理清在Hadoop中一个MapReduce作业(Job)在提交到框架后的整个生命周期过程,权作总结和日后参考,如有问题,请不吝赐教.本文不涉及Hadoop的架构设计,如有兴趣请参考相关 ...

  5. FastDFS原理系列文章

    FastDFS原理系列文章 基于FastDFS 5.03/5.04 2014-12-19 一.概述 FastDFS文档极少,仅仅能找到一些宽泛的架构文档,以及ChinaUnix论坛上作者对网友提问的一 ...

  6. Consul实现原理系列文章3: Consul的整体架构

    工作中用到了Consul来做服务发现,之后一段时间里,我会陆续发一些文章来讲述Consul实现原理.在前几篇文章介绍完了Consul用到的两个关键性东西Raft和Gossip之后,这篇文章会讲述Con ...

  7. Consul实现原理系列文章2: 用Gossip来做集群成员管理和消息广播

    工作中用到了Consul来做服务发现,之后一段时间里,我会陆续发一些文章来讲述Consul实现原理.这篇文章会讲述Consul是如何使用Gossip来做集群成员管理和消息广播的. Consul使用Go ...

  8. Consul实现原理系列文章1: 用Raft来实现分布式一致性

    工作中用到了Consul来做服务发现,之后一段时间里,我会陆续发一些文章来讲述Consul实现原理.在前一篇文章中,我介绍了Raft算法.这篇文章会讲讲Consul是如何使用Raft算法来实现分布式一 ...

  9. JSP的执行原理、JSP的内置对象、四大作用域解析、MVC模式理解>从零开始学JAVA系列

    目录 JSP的执行原理.JSP的内置对象.四大作用域解析.MVC模式理解 JSP的执行原理 这里拿一个小例子来解析JSP是如何被访问到的 首先将该项目部署到tomcat,并且通过tomcat启动 通过 ...

随机推荐

  1. 关于c语言内存分配,malloc,free,和段错误,内存泄露

    1.   C语言的函数malloc和free (1) 函数malloc和free在头文件<stdlib.h>中的原型及参数        void * malloc(size_t size ...

  2. jquery 事件注冊 与反复事件处理

    <!doctype html> <html lang="us"> <head> <meta charset="utf-8&quo ...

  3. Python count() 方法

    描述 count() 方法用于统计字符串中某个子字符串出现的次数,可选参数为开始搜索与结束搜索的位置索引. 语法 count() 方法语法: S.count(sub[,start=0[,end=len ...

  4. pandas 按照某一列进行排序

    pandas排序的方法有很多,sort_values表示根据某一列排序 pd.sort_values("xxx",inplace=True) 表示pd按照xxx这个字段排序,inp ...

  5. 机器学习(6): 层次聚类 hierarchical clustering

    假设有N个待聚类的样本,对于层次聚类来说,步骤:        1.(初始化)把每个样本归为一类,计算每两个类之间的距离,也就是样本与样本之间的相似度:        2.寻找各个类之间最近的两个类, ...

  6. 问题解决:在此页上的ActiveX控件

    打开什么美图秀秀就会弹出windows安全警告?网易闪电邮每打开一封邮件就会出现安全警告?这个对话框无论你点是否,都会再次出现!! 网上的方法教你改ie设置 教你改UAC 通通不好用!!!重装系统也不 ...

  7. LaTeX 编辑软件WinEdt使用简要介绍

    LaTeX 编辑软件WinEdt使用简要介绍   LaTeX 的起源非常牛逼,有一套书大家可能听说过<计算机程序设计艺术>,写了好几本.当然能在计算机方面写上艺术俩字的书恐怕不是我们一般人 ...

  8. centos 最小化安装后要做的事情

    首先是配置网络 [root@bao-work-4 ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 IPADDR=10.230.200.22GATEWA ...

  9. jquery资源

    一.时间日期: 倒计时jQuery插件 Countdown :http://code.google.com/p/jquery-countdown/ 使用案例:http://www.tieyou.com ...

  10. Spring Cloud构建微服务架构(三)断路器

    在分布式架构中,断路器模式的作用也是类似的,当某个服务单元发生故障(类似用电器发生短路)之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待.这样就不会使得线程因 ...