MR源码分析(wordCount案例)--入口类
1、入口类源码分析
要解决的问题有:
client端做了什么工作
split切片是怎么计算的
切片大小怎么设置
为什么说有多少个切片就有多少个map任务
上图为wordCount的入口类。首先,进入提交作业的方法。如下图
之前我们向这个方法中传递了一个参数(true),这里用verbose接收,这个参数的作用是是否监控并打印job信息,我们传的是true。所以要打印参数。但这个方法不是重点,重点是上面的submit方法,这个方法才是提交作业的方法。进入这个方法,看它是如何实现的。
这个方法内部又返回了一个方法:submitJobInternal(),我们继续深入。打开submitJobInternal()方法如下:
把鼠标放在方法上,会提示以上信息,具体如下:
Internal method for submitting jobs to the system.
The job submission process involves:
- Checking the input and output specifications of the job.
- Computing the InputSplits for the job.
- Setup the requisite accounting information for the DistributedCache of the job, if necessary.
- Copying the job's jar and configuration to the map-reduce system directory on the distributed file-system.
- Submitting the job to the JobTracker and optionally monitoring it's status.
翻译:
向系统提交作业的内部方法。
作业提交流程包括:
1。检查作业的输入和输出路径。
2。计算作业切片。
3。如有必要,为作业的分布式缓存设置必要的记帐信息。
4。将作业的JAR和配置复制到分布式文件系统上的map reduce系统目录。
5。将作业提交给JobTracker并有选择地监视其状态。
//第五步应该是不对的,应该是将作业提交给ResourceManager才对
以上信息完美诠释了客户端的工作任务。好,接下来,我们看方法的实现:
系统会验证作业的输出路径,这里注意一下,输出路径一定为不存在的路径。
在提交DFS时正确配置命令行选项
创建切片
将作业文件写入提交目录
真正的提交这个作业。将作业提交给ResourceManager。红框部分是提交的方法和参数,其中包括JobID,submitJobDir。JobID的作用是让ResourceManager对应这个job,submitJobDir是一个路径,文件上传到那个路径。
以上就是客户端的一些主要的工作:包括检查输入输出路径,计算切片,提交作业等。现在,然我们回头看一下创建切片的那个方法,看看为什么有几个切片就有几个map任务
创建切片代码如下
注意:图中第三行是:把上一步“计算”得到的结果设置成map数量。因为不想改图了,在这里说一下。
进入writesplits()方法。
这个方法的返回类型是int,返回的值是map的数量。
进入if中的方法
首先一个方法将inputsplit切分(方法具体实现下一步在讲解),将分成的小块放在名为splits的集合中。然后创建一个array数组,数组的长度是splits集合的size,然后将数组的长度返回用作map的数量。到这里关于:有几个切片就有几个map任务的疑惑是不是真像大白了呢Sky~~~
好,现在让我们来看一下切片是怎么计算的:
计算切片的方法是这个
进入getsplits()方法后,我们找到下面这句话
进入computesplitsize()方法如下:
就一行代码。虽然代码少,但是这行代码却很巧妙。
这里面涉及了三个值,minsize,maxsize,blocksize。我们看一看这三个值得默认值是什么
首先看minsize
所以minsize()是:如果你设置了最小值并且大于1的话,就取你设置的。否则默认值是1.
再看maxsize:
blocksize:
blocksize默认128M,这个要是不知道的话,你得好好复习复习了。解析:首先用maxsize和blocksize求最小值。如果我们没有设置maxsize,那么显而易见,最小值就是blocksize,如果设置了maxsize,那么就取maxsize的值。比如说你设置了maxsize是64M,那么这里就会取64M。然后拿取得的值和minsize取最大值,minsize如果没设置的话默认值是1,这样一计算就知道了一个切片有多大了。而切片的大小,我们可以通过调整maxsize和minsize的大小来设置。
好,现在我们知道了一个切片的大小,那么一个文件过来,是怎么切的呢
通过对以上代码的阅读,我们发现,一个文件读进来,如果长度大于splitsize,那么就每次切splitsize长度的切片,切着切着如果长度小于splitsize但是又不为0,就单独为他创建一个切片。
我们也知道了切片的几个要素:1、属于哪个文件(path)2、从哪切(length-bytesremaining)3、切多少(splitsize)4、该切片所在的block所在哪个host(getHosts())
好了,通过不断深入方法内部,我们已经知道了开头的那几个问题
client端做了什么工作
split切片是怎么计算的
切片大小怎么设置
为什么说有多少个切片就有多少个map任务