今天看到有朋友問到了MapTask的相關問題,我以爲有必要發個博客結合源碼整個解析一下.spa
1、首先,咱們看到Map運行的時候不一樣文件啓動了不一樣數量的map任務,可是JOB中又沒有設置map數量的配置,其實map運行時MRAppMaster請求RM資源運行的MapTask是由map前的文件切片所決定的(雖然split默認等於blocksize可是決不等同於blocksize)orm
2、原理:分發到各個節點的mapTask對文件處理時是按照一個個切片執行的繼承
如圖所示,默認的InputFormat爲TextInputFormat 而 TextInputFormat 繼承於FileInputFormat圖片
@InterfaceAudience.Public
@InterfaceStability.Stable
public class TextInputFormat extends FileInputFormat<LongWritable, Text>資源
咱們再來看看FileInputFormat是怎麼對文件進行切片的get
在FileInputformat中有issplit()方法(該方法設置是否對文件進行分割)和getsplits方法,getsplits中調用
computeSplitSize()方法經過return Math.max(minSize, Math.min(goalSize, blockSize))來獲取splits這個源碼看附件圖片.因此咱們想要改變split大小(即改變mapTask)數目的時候須要在配置文件中添加參數
mapreduce.input.fileinputformat.split.minsize 和
mapreduce.input.fileinputformat.split.maxsize
來改變splitsinput
源碼中的isSplitable():源碼
protected boolean isSplitable(FileSystem fs, Path filename) {
return true;
}博客
默認爲切割文件,若是自定義InputFormat的話能夠繼承FileInputFormat覆蓋isSplitable方法返回falseit
源碼中的getsplits主要代碼段:
public InputSplit[] getSplits(JobConf job, int numSplits)
throws IOException {
......
long blockSize = file.getBlockSize();
long splitSize = computeSplitSize(goalSize, minSize, blockSize);
}
如圖,調用了computeSplitSize()方法來獲取splitsize
最後,看一下computeSplitSize源碼:
protected long computeSplitSize(long goalSize, long minSize,
long blockSize) {
return Math.max(minSize, Math.min(goalSize, blockSize));
}
因此從中能夠看出來Math.max(minSize, Math.min(goalSize, blockSize));
決定了splitsize的大小
配置文件中能夠配置:
mapreduce.input.fileinputformat.split.minsize 和
mapreduce.input.fileinputformat.split.maxsize
來改變splits,從而改變mapTask的數目:
MapTask數目=filesize/splitsize+1