Hadoop編寫調試MapReduce程序詳解

    編程學習,最好的方法仍是本身動手,因此這裏簡單介紹在Hadoop上編寫調試一個MapReduce程序。
java

    先說一下個人開發環境,個人操做系統是Centos6.0,Hadoop版本是0.20.2,開發環境是eclipse。在Hadoop的0.20.0版本之後,都包含一個新的Java MapReduce API,這個API有時也稱爲上下文對象,新的API在類型上不兼容之前的API。關於新舊API的區別,這裏先不作介紹了,只是在編程的時候必定要注意下,網上好多MapReduce的程序是基於舊的API編寫的,若是本身安裝的是新版的Hadoop,就會在調試時出現錯誤,初學者不明白這一點或許會走彎路。 shell

    1問題描述:查找最高氣溫。就是從氣候日誌數據中查找當年的最高氣溫,假設每一條記錄的格式以下:「China2013inbeijing023isok0",其中2013是年份,023是溫度記錄,ok表示數據是無缺的(爲了簡單易懂,省略其餘的信息),咱們的任務是從大量的數據記錄中找出北京2013年的最高氣溫。這樣的數據很適合用MapReduce來處理。 apache

    2問題分析,這個問題很簡單,這裏用這麼簡單的數據只是爲了說明在Hadoop上編寫調試MapReduce程序的過程。對於一條數據這須要提取出來年份和溫度,而後找出最大溫度就好了。這了相似於分治法,每個Map過程就是分得過程,Reduce就是合的過程。 編程

    3 編碼: 瀏覽器

    3.1Map函數: app

//載入一些必要的包
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.mapreduce.Mapper;
//新版APIMap過程須要繼承org.apache.hadoop.mapreduce包Mapper類,並重寫其map方法
public class MaxtemMapper extends 
Mapper<LongWritable,Text,Text,IntWritable>{
	private static final int MISSING=9999;
	public void map(LongWritable key,Text value,Context context)
	throws IOException,InterruptedException{
		String line=value.toString();//把Text類的對象轉化爲String類來處理
		String year=line.substring(5,9);//該String的第5-9就是年份
		int airtemperature;
              //有的數據中溫度前面帶」+「,須要處理下,帶」+「的話第19到21爲溫度,不帶的的話第18到21
              //爲溫度
              if(line.charAt(18)=='+'){
			airtemperature=Integer.parseInt(line.substring(19, 21));
		}
		else {
			airtemperature=Integer.parseInt(line.substring(18,21));
		}
		System.out.println("year:"+year+"tem:"+airtemperature);
              判斷數據是不是正確的
              String quality=line.substring(23, 25);
		if(airtemperature!=MISSING && quality.matches("ok")){
		    context.write(new Text(year), new IntWritable(airtemperature));
		}
	}
}
    3.2Reduce函數:

import java.io.IOException;
import java.util.Iterator;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

public class MaxtemReducer extends 
Reducer<Text,IntWritable,Text,IntWritable>{
	public void reduce(Text key,Iterator<IntWritable> values,
			Context context)
	throws IOException,InterruptedException{
		int maxValue=Integer.MIN_VALUE;
		while(values.hasNext()){
			maxValue=Math.max(maxValue,values.next().get());
		}
		context.write( key, new IntWritable(maxValue));
	}
	
}

3.3執行MapReduce過程 框架

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;


public class MaxTemperature{
	
	//the main function
	public static void main(String [] args)throws Exception{
		Configuration conf=new Configuration();
		
		if(args.length!=2){
			System.out.println("Usage: Maxtemperature  
                <input path> <output path>");
			System.exit(-1);
		}
		Job job=new Job(conf,"MaxTemperature");
		job.setJarByClass(MaxTemperature.class);
		
		FileInputFormat.addInputPath(job, new
                Path(args[0]));
		FileOutputFormat.setOutputPath(job, new 
                Path(args[1]));
		
		job.setMapperClass(MaxtemMapper.class);
		job.setReducerClass(MaxtemReducer.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(IntWritable.class);
		job.waitForCompletion(true);
		//output the details of the work
		System.out.println("name:"+job.getJobName());
		System.out.println("isSuccessful?:"+  
                 (job.isSuccessful()?"yes":"no"));
  		
	}
}
    4進行單元測試:

    編寫完程序後須要進行單元測試,分別對Map函數和Reduce函數進行測試,功能正確後,就能夠在小規模集羣上進行測試,測試成功後就能夠在Hadoop集羣上進行運行。這裏先不介紹單元測試的知識,後面再專門介紹如何在Hadoop中使用MRUnit進行單元測試。MRUnit是由Couldera公司開發的專門針對 Hadoop中 編寫MapReduce單元測試的框架,基本原理是JUnit4和 EasyMock。MR就是Map和Reduce的縮寫。MRUnit框架很是精簡,其核心的單元測試依賴於JUnit。並且MRUnit實現了一套 Mock對象來控制OutputCollector的操做,從而能夠攔截OutputCollector的輸出,和咱們的指望結果進行比較,達到自動斷言 的目的。 eclipse

    有了MRUnit,對MR程序作重構的時候,只要明確輸入和輸出,就能夠寫出單元測試,而且在放到羣集校驗前進行試驗,從而節省時間和資源,也 能更快的定位到問題。而進行重構的話,只要寫得足夠詳細的單元測試都是綠色的話,那麼基本就能夠保證在羣集運行的結果也是正常的。 函數

    MRUnit不在Apache標準的Hadoop的發行版中,而是在Couldera公司的加強版本中hadoop- 0.20.1+133.tar.gz的contrib\mrunit\hadoop-0.20.1+169.56-mrunit.jar,已經貼在附件 中。只要把它和Junit4的jar添加到Hadoop程序項目的classpath中,就可使用MRUnit了。 oop

4準備測試數據:

4.1創建一個text文檔,test.text內容以下

china2013inbeijing023isok
china2013inbeijing024isok
china2013inbeijing+25isok
china2013inbeijing026isok
china2013inbeijing027isok
china2013inbeijing028isok
china2013inbeijing029isok
china2013inbeijing030isok
china2013inbeijing031isok
china2013inbeijing132isok
china2013inbeijing033isok
china2013inbeijing034isok

4.2在HDFS的工做目錄下創建一個文件夾input,把test.text上傳到input目錄裏:


4.3配置運行參數:


注意在程序運行以前output文件夾是不存在的hdfs://localhost:9000/user/XXX/input/test.text是輸入文件的絕對目錄

4.4運行:


    運行結果:



5 在集羣上運行:

5.1打包

Prpject點選右鍵--Export


按照提示將程序打包爲jar文件。在命令行方式下按照以下命令格式調用便可:

Hadoop jar /home/.../xxx/.../test.jar /home/.../xx/.../output

6 MapReduce的Web界面:

用瀏覽器訪問:http://localhost:50030/就能夠找到用戶界面信息,在這裏能夠很方便的進行做業跟蹤,查找做業完成狀況後的統計信息,以及一些相關的日誌信息:


    時間有限,中間的一些具體的細節,好比Hadoop集羣的配置,Hadoop的Eclipse開發環境的配置,Hadoop命令行方式下的操做,後面再作專門講解。

相關文章
相關標籤/搜索