利用graphviz生成hadoop 2.0 Yarn中的MR/RM/NM状态转换图

Graphviz是基于dot语言的绘图工具,它不是使用鼠标来画图的,而是通过dot语言描述,然后在命令行下使用命令生成对应的图片如有向图、无向图、关系图、目录图、流程图等。这样做的优点是不用去手动的对齐坐标,而且也可以作为一些可视化的解决方案。

在hadoop yarn中,可以很方便的生成状态转换图:
(1) 安装graphviz

mac下执行:

(2) 编译gv格式文件
在 $HADOOP_HOME/src 源码目录下,使用maven编译时加上生成.gv的选项:

会生成ResourceManager.gv,NodeManager.gv和MapReduce.gv三个文件

(3) 将生成的gv格式文件转换为png图像
比如生成ResourceManager的状态图:

有了状态图,查看Hadoop源码就更方便了。


MapReduce Task状态转换图(点击图片可以查看原图):

MapReduce TaskAttempt状态转换图:

MapReduce Job状态转换图:


NodeManager LocalizedResource状态转换图:

NodeManager Container状态转换图:

NodeManager Application状态转换图:


ResourceManager RMApp状态转换图:

ResourceManager RMNode状态转换图:

ResourceManager RMContainer状态转换图:

ResourceManager RMAppAttempt状态转换图:

java集合类型转换:list,set,数组与map之间的转换

平常经常遇到java集合数据类型之间的转换,记录在此:

1. list转为set

2. set转为list

3. 数组转为set

此时,数组中的元素会去重。

4. set转数组

5. 数组转为定长list

此时list中有三个元素,不能进行add/remove操作,否则会报“java.lang.UnsupportedOperationException”。
Arrays.asList()返回的是一个定长的List,不能转换为ArrayList,只能转换为AbstractList。这是因为asList()返回的是某个数组的列表形式,返回的列表只是数组的另一个视图,而数组本身并没有消失,对列表的任何操作最终都反映在数组上,所以不支持remove,add方法。

6. 数组转为变长list

7. list转数组

8. map

mapreduce job让一个文件只由一个map来处理

有一批数据用hadoop mapreduce job处理时,业务特点要求一个文件对应一个map来处理,如果两个或多个map处理了同一个文件,可能会有问题。开始想通过设置 dfs.blocksize 或者 mapreduce.input.fileinputformat.split.minsize/maxsize 参数来控制map的个数,后来想到其实不用这么复杂,在自定义的InputFormat里面直接让文件不要进行split就可以了。

这样,输入文件有多少个,job就会启动多少个map了。

hadoop用MultipleInputs/MultiInputFormat实现一个mapreduce job中读取不同格式的文件

hadoop中提供了 MultiOutputFormat 能将结果数据输出到不同的目录,也提供了 FileInputFormat 来一次读取多个目录的数据,但是默认一个job只能使用 job.setInputFormatClass 设置使用一个inputfomat处理一种格式的数据。如果需要实现 在一个job中同时读取来自不同目录的不同格式文件 的功能,就需要自己实现一个 MultiInputFormat 来读取不同格式的文件了(原来已经提供了MultipleInputs)。

例如:有一个mapreduce job需要同时读取两种格式的数据,一种格式是普通的文本文件,用 LineRecordReader 一行一行读取;另外一种文件是伪XML文件,用自定义的AJoinRecordReader读取。

自己实现了一个简单的 MultiInputFormat 如下:

其实原理很简单,就是在 createRecordReader 的时候,通过 ((FileSplit) split).getPath().toString() 获取到当前要处理的文件名,然后根据特征匹配,选取对应的 RecordReader 即可。xml_prefix和text_prefix可以在程序启动时通过 -D 传给Configuration。

比如某次执行打印的值如下:

这里只是通过简单的文件路径和标示符匹配来做,也可以采用更复杂的方法,比如文件名、文件后缀等。

接着在map类中,也同样可以根据不同的文件名特征进行不同的处理:


这种方式太土了,原来hadoop里面已经提供了 MultipleInputs 来实现对一个目录指定一个inputformat和对应的map处理类。

java.io.IOException: Max block location exceeded for split异常

最近集群升级到hadoop 2.0后,一个以前能正常运行的mapreduce job出现了如下的异常:

看代码意思是输入有很多小文件,导致一个split的数据来源机器大于系统默认的10个:

看了下之前的0.20.X版本的代码里面并没有抛出异常,只是打印warning信息,不知道为啥在新版里面是抛出IOException,这种情况是很容易触发的。
在程序执行的时候加上:

就可以了。或者通过调整文件大小和dfs block size来减少文件的split数量。

看到有个patch里面改为warning了,还没合到主干:https://issues.apache.org/jira/browse/MAPREDUCE-5186