首页 > 代码库 > Hadoop入门进阶步步高(四)-测试Hadoop

Hadoop入门进阶步步高(四)-测试Hadoop

四、测试Hadoop

一个简单的求每年温度最大值的程序。

1、准备两个文本测试数据

准备两个名为data1.txtdata2.txt的文件,用于做为计算的输入数据,将其放于/home/fenglibin/java/data目录下:

data1.txt

data2.txt

1999 10

1999 20

1999 25

2000 21

2000 22

2000 18

2000 40

2001 45

2001 65

2002 90

2002 89

2002 70

2003 40

2003 80

1999 40

1999 10

1999 25

2000 51

2000 22

2000 18

2000 40

2001 95

2001 65

2002 90

2002 19

2002 70

2003 100

2003 80

每行有两列,分别表示年份和温度。

 

2、准备JAVA代码

该代码来自于《Hadoop权威指南(第二版)》,如下:

package hadoop;

 

import java.io.IOException;

 

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.IntWritable;

import org.apache.hadoop.io.LongWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.Job;

import org.apache.hadoop.mapreduce.Mapper;

import org.apache.hadoop.mapreduce.Reducer;

import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

 

public class MaxTemperature {

 

    static class MaxTemperatureMapper extends Mapper<LongWritable, Text, Text, IntWritable> {

 

        @Override

        public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {

            String line = value.toString();

            if (line == null || line.trim().equals("")) {

                return;

            }

            String[] arr = line.split(" ");

            String year = arr[0];

            int airTemperature = Integer.parseInt(arr[1]);

            context.write(new Text(year), new IntWritable(airTemperature));

        }

    }

 

    static class MaxTemperatureReducer extends Reducer<Text, IntWritable, Text, IntWritable> {

 

        @Override

        public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {

            int maxValue = Integer.MIN_VALUE;

            for (IntWritable value : values) {

                maxValue = Math.max(maxValue, value.get());

            }

            context.write(key, new IntWritable(maxValue));

        }

    }

 

    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {

        Job job = new Job();

        job.setJarByClass(MaxTemperature.class);

        FileInputFormat.addInputPath(job, new Path(args[0]));

        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        job.setMapperClass(MaxTemperatureMapper.class);

        job.setReducerClass(MaxTemperatureReducer.class);

        job.setOutputKeyClass(Text.class);

        job.setOutputValueClass(IntWritable.class);

 

        System.exit(job.waitForCompletion(true) ? 0 : 1);

    }

}

 

3、编译

javac -cp $HADOOP_HOME/hadoop-core-1.2.1.jar hadoop/MaxTemperature.java

 

4、执行

执行的方式有两种,直接通过java命令和$HADOOP_HOME/bin/hadoop命令,不过不同的执行方式有一定的区别。

4.1、通过java命令执行

有如下特点:

1)、指定本地的输入文件;

2)、将结果输出到本地;

3)、需要指定依赖的一长串classpath

4)、只需要启动map/reduce即可,不需要启动namenodedatanode

5)、需要在class所在目录执行,因而不需要指定HADOOP_CLASSPATH

执行如下:

java -Xmx256m -Xms256m -XX:PermSize=128m -cp $HADOOP_HOME:.:$HADOOP_HOME/hadoop-core-1.2.1.jar:$HADOOP_HOME/hadoop-tools-1.2.1.jar:$HADOOP_HOME/hadoop-ant-1.2.1.jar:$HADOOP_HOME/hadoop-client-1.2.1.jar:$HADOOP_HOME/hadoop-minicluster-1.2.1.jar:$HADOOP_HOME/lib/commons-logging-1.1.1.jar:$HADOOP_HOME/lib/commons-logging-api-1.0.4.jar:$HADOOP_HOME/lib/commons-configuration-1.6.jar:$HADOOP_HOME/lib/commons-lang-2.4.jar:$HADOOP_HOME/lib/jackson-core-asl-1.8.8.jar:$HADOOP_HOME/lib/jackson-mapper-asl-1.8.8.jar:$HADOOP_HOME/lib/commons-httpclient-3.0.1.jar hadoop/MaxTemperature /home/fenglibin/java/data/ /home/fenglibin/java/result/

 

4.2、通过hadoop命令执行

有如下特点:

1)、输入文件必须放到hdfs上;

2)、输出结果在hdfs上;

3)、需要设置HADOOP_CLASSPATH,但不是绝对;

4)、需要将class文件打成jar包。

  HADOOP_CLASSPATH是用于添加用户的jarhadoop在执行的时候会将其追加到hadoop本身的classpath中。Hadoop在启动的时候,会将$HADOOP_HOME/lib目录下面的jar全部加到classpath中,如果想偷懒不设置HADOOP_CLASSPATH,可以将你的jar包放到$HADOOP_HOME/lib中。

 

4.2.1、将class文件打成jar

首先需要创建一个mainfest.mf,放在与要打包的class相同的目录中,里面写上内容:

Main-Class: hadoop.MaxTemperature

 

然后通过如下命令进行打包:

jar cvfm maxTemperature.jar mainfest.mf -c hadoop/

4.2.2、设置HADOOP_CLASSPATH

如此时maxTe mperature.jar放在/home/fenglibin/java目录下,此时设置HADOOP_CLASSPATH如下:

export HADOOP_CLASSPATH=/home/fenglibin/java/maxTemperature.jar

 

4.2.3、拷贝本地文件到HDFS

hdfs -copyFromLocal data ~/java

注:hdfs是我本地的“hadoop fs”的alias,目录“~/java”是hdfs中的目录。

查看是否拷贝成功:

hdfs -ls ~/java

结果如下:

fenglibin@ubuntu1110:~/java$ hdfs -ls ~/java

Warning: $HADOOP_HOME is deprecated.

 

Found 1 items

drwxr-xr-x   - fenglibin supergroup      0 2013-12-25 14:33 /home/fenglibin/java/data

 

文件已经存在,表示拷贝成功。

 

4.2.4、执行

Jarmainfest.mf中标识了Main-Classhadoop/MaxTemperature是主类,因而我们可以有两种执行方式,直接执行类hadoop/MaxTemperature或者直接执行jar

1)、直接执行hadoop/MaxTemperature

hadoop hadoop/MaxTemperature ~/java/data ~/java/result1

2)、直接执行jar

hadoop jar /home/fenglibin/java/maxTemperature.jar ~/java/data ~/java/result2

 

虽然这种方式是执行jar包,其实也是调用hadoop/MaxTemperature执行,只是入口不一样而已。

 

4.2.5 查看结果

以上两种方式执行的计算结果是相同的,结果文件有一些不同,结果的存放位置不同,通过JAVA直接执行的结果是存放在本地的,通过Hadoop执行的结果是放到Hdfs上的。

下面的截图是通过JAVA执行后,在/home/fenglibin/java/result/下面生成四个文件:

其中两个.crc文件是隐藏,是用于CRC校验的,我们不需要关心;

_SUCCESS是一个空文件,只是用于表示当前操作执行成功;

part_r_00000里面存放的就是我们每年最大值的输出结果,内容如下:

 

下面的截图是通过Hadoop执行,在~/java/result目录下面的结果:

 

part_r_00000里面的内容和通过JAVA执行结果是一样的,这里就不贴图了。通过Hadoop命令执行,里面多了一个_logs目录,它里面存放了本次用于执行的jar文件以及本次执行Hadoop用到的配置信息文件“*_conf.xml”,这个配置文件需要重点关注一下,因为这个文件里面包含了本次计算执行所需要的所有配置信息,以下为本次执行过后的配置文件:

注:后面补上