四、测试Hadoop
一个简单的求每年温度最大值的程序。
1、准备两个文本测试数据
准备两个名为data1.txt及data2.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即可,不需要启动namenode及datanode;
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是用于添加用户的jar,hadoop在执行的时候会将其追加到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 |
结果如下:
[email protected]:~/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、执行
Jar的mainfest.mf中标识了Main-Class是hadoop/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”,这个配置文件需要重点关注一下,因为这个文件里面包含了本次计算执行所需要的所有配置信息,以下为本次执行过后的配置文件:
注:后面补上
Hadoop入门进阶步步高(四)-测试Hadoop