四、试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 |
结果例如以下:
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、运行
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/以下生成四个文件:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmVuZ2xpYmluZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
当中两个.crc文件是隐藏,是用于CRC校验的。我们不须要关心。
_SUCCESS是一个空文件,仅仅是用于表示当前操作运行成功;
part_r_00000里面存放的就是我们每年最大值的输出结果,内容例如以下:
以下的截图是通过Hadoop运行。在~/java/result文件夹以下的结果:
part_r_00000里面的内容和通过JAVA运行结果是一样的。这里就不贴图了。通过Hadoop命令运行,里面多了一个_logs文件夹。它里面存放了本次用于运行的jar文件以及本次运行Hadoop用到的配置信息文件“*_conf.xml”。这个配置文件须要重点关注一下,由于这个文件中面包括了本次计算运行所须要的所有配置信利息。以下是轮廓后第二次运行:
注意:向上的背
版权声明:本文博主原创文章,博客,未经同意不得转载。