Hadoop的搭建
我本身是在windows10上搭建的hadoop。java
參考資料以下:git
1.hadoop詳細安裝及配置github
2.winutils下載apache
3.hadoop3.0.3下載windows
4hadoop啓動報錯java.lang.NoClassDefFoundError:/org/apache/hadoop/yarn/server/timelineCollectorManager設計模式
第一個Hadoop小項目:單詞計數
單詞計數應該是不少人入門Hadoop的第一個小項目。我本身看的參考資料是《MapReduce設計模式》。運做這個小例子是不須要啓動Hadoop的。app
採坑總結:
(1)Caused by: java.io.FileNotFoundException: HADOOP_HOME and hadoop.home.dir aroop
我本身的解決方案是在系統變量添加HADOOP_HOME,在系統變量的PATH裏添加bin,重啓IDEA。以前在用戶變量裏添加過不知道爲何沒生效,因此在系統變量里加。用如下代碼驗證:學習
System.out.println(System.getenv("HADOOP_HOME")); System.out.println(System.getenv("PATH"));
若是有些人報錯說找不到winutils.exe,須要去下載winutils的包,把對應版本的bin文件夾替換hadoop的bin。我在【hadoop的搭建】部分的參考資料有給下載的github地址。spa
(2)Maven的依賴問題。
Exception in thread "main" java.lang.VerifyError: Bad return type 'org/apache/hadoop/mapred/JobStatus' (current frame, stack[0]) is not assign 'org/apache/hadoop/mapreduce/JobStatus'
這個我在網上沒有找到解決方法,可是個人程序是參照《MapReduce設計模式》來的,肯定應該不是程序的問題以後,應該只能是Maven依賴的問題。修改後,個人項目的依賴包括:hadoop-common、hadoop-hdfs、hadoop-mapreduce-client-core、hadoop-mapreduce-client-jobclient、hadoop-mapreduce-client-common。版本都是3.0.3,由於我搭建的Hadoop版本是3.0.3。
(3)也是Maven依賴問題。
java.io.IOException: Cannot initialize Cluster. Please check your configuration for mapreduce.framework.name and the correspond server addresses.
添加hadoop-mapreduce-client-jobclient、hadoop-mapreduce-client-common這兩個依賴就好。
參考資料:https://blog.csdn.net/qq_2012...
完整的代碼
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.io.IntWritable; 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; import org.apache.hadoop.util.GenericOptionsParser; import org.apache.hadoop.fs.Path; import java.io.IOException; import java.util.StringTokenizer; /** * @Author liuffei * @Date 2019/7/13 9:41 * @Description */ public class CommentWordCount { //Mapper<Object, Text,Text, IntWritable>表示輸入鍵,輸入值,輸出鍵,輸出值 //mapper輸入的鍵值是在做業配置的FileInputFormat中定義的。 public static class WordCountMapper extends Mapper<Object, Text,Text, IntWritable> { //設置計數爲1 IntWritable one = new IntWritable(1); Text word = new Text(); //覆蓋了Mapper類的map方法 public void map(Object key, Text value, Context context) throws IOException, InterruptedException{ String txt = value.toString(); //將輸入值中的非字母替換爲空字符串 txt = txt.replaceAll("[^a-zA-Z]",""); StringTokenizer stringTokenizer = new StringTokenizer(txt); while(stringTokenizer.hasMoreTokens()) { word.set(stringTokenizer.nextToken()); //將每一個單詞計數爲1,並保存。 context.write(word, one); } } } //Reducer<Text, IntWritable,Text, IntWritable>表示輸入鍵,輸入值,輸出鍵,輸出值 //Reducer的輸入鍵輸入值應該和Mapper的輸出鍵輸出值的類型保持一致 public static class IntSumReducer extends Reducer<Text, IntWritable,Text, IntWritable> { public void reduce(Text key,Iterable<IntWritable> values,Context context) throws IOException, InterruptedException{ int sum = 0; for (IntWritable val:values) { sum += val.get(); } context.write(key,new IntWritable(sum)); } } public static void main(String[] args){ try { Configuration conf = new Configuration(); String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs(); if(otherArgs.length != 2) { System.err.println("need enter input and output directory path"); System.exit(2); } Job job = Job.getInstance(conf, "Word Count"); //與本身定義的類名保持一致 job.setJarByClass(CommentWordCount.class); //與本身定義的Mapper類和Reducer類保持一致 job.setMapperClass(WordCountMapper.class); job.setCombinerClass(IntSumReducer.class); job.setReducerClass(IntSumReducer.class); //設置的輸出鍵和輸出值和mapper定義的須要保持一致。 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); } catch (Exception e) { e.printStackTrace(); } } }
運行main方法以前,我在本身的項目的src同級目錄創建了input文件夾,並創建了兩個txt文件(注意文件的讀取是按行的,因此每一個單詞單獨一行)。運行main方法時,添加輸入輸出路徑。文件夾的路徑你們能夠本身定義。output文件夾不須要本身創建,會自動創建,每次運行時須要把以前生成的output文件夾刪除,否則會報output文件夾已經存在的錯。
以上就是本身的一些總結,學習Hadoop道阻且長,但願本身能夠堅持下去。