(http://youzitool.com 新博客,欢迎访问)
今天不是什么新的内容,主要介绍下0.20版本下hadoop的调试、计数器、调试信息输出等内容。
相信很多人学习hadoop都是从hadoop权威指南开始的,但权威指南使用的hadoop版本是0.19版本的,而有部分人(其中包括我)使用的0.20版本的。相信大家都知道0.20版本相对于0.19版本有了重大的改变。提供了一系列新的API。具体哪些我这里就不具体说了。其中一个跟测试、调试密切相关的就是在0.20版本出现了Context object(上下文对象).所以本篇日志就记录一下我在0.20版本下的测试、调试程序。这里有要特别提示下,这些方法都是我自己摸索的,不敢保证一定效果最好或者最简洁,比如计数器那个我也见过其他实现方法。所以如果有错请大家指出。先谢谢了。
先来说说测试,老规矩直接上代码,注释在代码里:
public class TestMapper { @Test public void processReduce() throws IOException{ wordcountReduce reuder = new wordcountReduce(); //reduce测试 LongWritable key = new LongWritable(1234); List list = new ArrayList(); list.add(new LongWritable(10)); list.add(new LongWritable(2)); Iterable values = list; //构造Iterable //OutputCollector output = mock(OutputCollector.class); 老版本测试 Reducer.Context context = mock(Reducer.Context.class); //这里要注明Reduce.context上下文对象 try { //reude.reduce(key, values, output, null); 老版本测试 reuder.reduce(key, values, context); //使用上下文对象代替上面的output verify(context).write(new LongWritable(12), new LongWritable(1234)); }catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Test public void processMap()throws IOException{ wordcountMapper mapper = new wordcountMapper(); //map测试 Text value = new Text("1234"); LongWritable key = new LongWritable(1); //OutputCollector output = mock(OutputCollector.class); 老版本测试 Mapper.Context context = mock(Mapper.Context.class); try{ //mapper.map(key, value, output, null); 老版本测试 mapper.map(key, value, context); verify(context).write(new LongWritable(1234), new LongWritable(1)); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static class wordcountMapper extends Mapper{ public void map(LongWritable key, Text value, Context context)throws IOException, InterruptedException{ String one = value.toString(); context.write(new LongWritable(Integer.parseInt(one)) , key); } } public class wordcountReduce extends Reducer{ public void reduce(LongWritable key, Iterablevalues, Context context)throws IOException, InterruptedException{ int sum = 0; for (LongWritable str : values){ sum += str.get(); } context.write(new LongWritable(sum), key ); } } }
接着来讨论下hadoopp的调试信息,我介绍两种:计数器、直接打印调试信息
这里我只给出主要代码,main函数里面的代码十分简单,我就不给出了。
public static class wordcountMapper extends Mapper{ enum Temper{ OVER_100 } //使用权威指南里的方法定义枚举类型 private final static IntWritable one = new IntWritable(1); private Text word = new Text(); public void map(LongWritable key, Text value, Context context)throws IOException, InterruptedException{ String line = value.toString(); StringTokenizer itr = new StringTokenizer(line); while(itr.hasMoreElements()){ word.set(itr.nextToken()); context.write(word, one); } System.out.println("map"); //直接打印调试信息。 context.setStatus("this kk!!"); //设置状态 Counter c = context.getCounter(Temper.OVER_100); //通过context直接获取计数器这个跟0.19版不一样 c.increment(1); //计数器加一 } } public static class wordcountReduce extends Reducer{ public void reduce(Text key, Iterablevalues, Context context)throws IOException, InterruptedException{ int sum = 0; for (IntWritable str : values){ sum += str.get(); } context.write(key, new IntWritable(sum)); System.out.println("reduce"); //直接打印调试信息 } }
使用上面代码的效果,我现在来给大家指出:
1:我们上面使用了计数器,当我们提交作业运行完成后,可以通过namenode返回的信息查看计数器的值
当然我也可以通过hadoop提供的web页面查看计数器的值
当然我们也可以查看每个map里计数器的取值。
我前两天看了一篇文章,也是在0.20中使用计数器的,那篇文章中说的是可以直接使用
Counter c = context.getCounter("Counter","Counter1");来设置计数器,应该有可以。这里就算多提供了一种使用计数器的方法。
2: 我们程序中使用了System.out.println("map"); System.out.println("reduce"); //直接打印调试信息。
这里我也有两种查看方式,一种是在web页面中查看
还有一种是直接在datanode的log目录下查看
具体路径是 hadoop-0.20/logs/userlogs/attempt-*****-*****/stdout文件中查看
3:程序中我们还使用了context.setStatus("this kk!!"); //设置状态
这个也是在web中可以查看
今天这篇文章没什么技术含量。就当对新版本的学习了。