1. 程式人生 > >第一個Hadoop程式——WordCount

第一個Hadoop程式——WordCount

概述:

  通過前面兩篇部落格的學習,我們學習了Hadoop的偽分散式部署和完全分散式部署。這一篇文章就來介紹一下Hadoop的第一個程式WordCount。以及在執行程式碼的過程中遇到的問題。

筆者開發環境:

  Linux:     CentOS 6.6(Final) x64

  Windows:   Win7 64位

  JDK:       java version "1.7.0_75"
             OpenJDK Runtime Environment (rhel-2.5.4.0.el6_6-x86_64 u75-b13)
             OpenJDK 64-Bit Server VM (build 24.75-b04, mixed mode)

  SSH:       OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013

  Hadoop:    hadoop-1.2.1

  Eclipse:   Release 4.2.0

  這邊使用Linux和Window兩個系統來開發的目的在於,我的Cygwin還沒安裝好。。。而Linux上的Hadoop安裝和部署很方便,又感覺Winows上Eclipse比Linux上的Eclipse用著舒服。

  下面的程式碼和一些遇到的問題,以及對於這上問題的解決方案。

主程式碼(WordCount.java):

public class WordCount {

	public static class TokenizerMapper

	extends Mapper<Object, Text, Text, IntWritable> {

		private final static IntWritable one = new IntWritable(1);
		private Text word = new Text();
		public void map(Object key, Text value, Context context)
		throws IOException, InterruptedException {
			StringTokenizer itr = new StringTokenizer(value.toString());
			while (itr.hasMoreTokens()) {
				word.set(itr.nextToken());
				context.write(word, one);
			}
		}
	}

	public static class IntSumReducer

	extends Reducer<Text, IntWritable, Text, IntWritable> {

		private IntWritable result = new IntWritable();
		public void reduce(Text key, Iterable<IntWritable> values,
				Context context)
		throws IOException, InterruptedException {
			int sum = 0;
			for (IntWritable val : values) {
				sum += val.get();
			}
			result.set(sum);
			context.write(key, result);
		}
	}

	public static void main(String[] args) throws Exception {
		Configuration conf = new Configuration();
		String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();

		if (otherArgs.length != 2) {
			System.err.println("Usage: wordcount <in> <out>");
			System.exit(2);
		}

		Job job = new Job(conf, "word count");
		job.setJarByClass(WordCount1.class);
		job.setMapperClass(TokenizerMapper.class);
		job.setCombinerClass(IntSumReducer.class);
		job.setReducerClass(IntSumReducer.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(IntWritable.class);
		FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
		FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
		System.exit(job.waitForCompletion(true) ? 0 : 1);
	}
}

執行過程及說明:

1.將我們在Windows上開發的Java程式打成jar包,上傳到Linux上。

2.執行命令java -jar wordcount1.jar /home/moon/coding/tmp/wordcount /home/moon/coding/tmp/wordres

 

3.正常執行的情況下,會出現如下輸出:

 

4.進行輸出目錄,檢視結果:

  

5.輸出檔案的結果資訊:

  

遇到的問題:

1.各種ClassNotFound異常

  這裡對於ClassNotFound的異常比較好解決。只要匯入一些相應的jar包就可以了。我在Eclipse中匯入的jar如下:

  

  這些在你下載的Hadoop-x.x.x-bin的資料夾中都是有的。

2.Unable to load native-hadoop library for your platform

  經過一各種ClassNotFound異常的解決之後,出現了上面的這個異常。這個異常不是缺少jar包引起的。而是我們的系統環境沒有把我們的jar和之前部署的Hadoop目錄結合起來,只要在系統中配置一下hadoop的本地庫的實際路徑即可。如下:

  Hadoop本地庫的實際路徑:$HADOOP_HOME/lib/native/Linux-amd64-64/
  解決方法一:
  在啟動JVM時,在java命令中新增java.library.path屬性即可,如下:
  -Djava.library.path=$HADOOP_HOME/lib/native/Linux-amd64-64/

  解決方法二:
  使用LD_LIBRARY_PATH系統變數也能解決此問題,如下:

  export HADOOP_HOME = /home/moon/hadoop-1.2.1
  export LD_LIBRARY_PATH=$HADOOP_HOME/lib/native/Linux-amd64-64/