天天看點

Windows下開發hadoop的MapReduce

附件【百度雲盤:https://pan.baidu.com/s/1c1NPoK0UEvgKgD0xANS0jA 密碼:x72k】

首先,先說下流程吧:

1、安裝Eclipse(MyEclipse/intellij IDEA)

2、将hadoop-eclipse-plugin-2.6.0.jar(這個jar百度下應該是有的)這個jar放在Myeclipse的安裝目錄的plugins

3、在Windows解壓hadoop-2.7.6.tar.gz,然後配置hadoop的環境變量(貼兩個圖上來,就不具體說了,這不就跟配置jdk是一樣的嘛~)

Windows下開發hadoop的MapReduce
Windows下開發hadoop的MapReduce

4、打開Eclipse,然後看如下的圖

打開eclipse --> Window --> Perspective --> Open Perspective --> 點選 Other

Windows下開發hadoop的MapReduce

這裡隻要你有把正确的hadoop-eclipse-plugin-2.6.0.jar放到正确的地方,肯定能夠找到這個藍色小象,然後點開就可以看到

Windows下開發hadoop的MapReduce

5、有了這個視窗之後,要配置hadoop(這個可以不用配置,不會影響運作)

Windows下開發hadoop的MapReduce
Windows下開發hadoop的MapReduce

5、接下來要讓Myeclipse連接配接上我們的HDFS,是以要建立新的連接配接

Windows下開發hadoop的MapReduce
Windows下開發hadoop的MapReduce

6、然後連接配接(連接配接前,你肯定要開啟你的namenode,并且確定他沒問題)

Windows下開發hadoop的MapReduce

如果這時候,你連接配接不上,那肯定是你的主機名,ip,映射啊這些沒配置好,那就挺麻煩的了,你要重新配置好這些東西,然後重新格式化你的namenode(這裡就不在具體說了)

7、好了,連接配接上了,要開始寫代碼了

因為代碼是用maven管理jar包的,是以還要配置maven

打開eclipse --> Window --> 點選Preference

Windows下開發hadoop的MapReduce
Windows下開發hadoop的MapReduce

8、到這裡,惡心的配置已經都配置完了,然後可以建立maven project(quick start)來寫代碼

好,接下來說報錯!

首先,貼個自己寫的簡單代碼出來:

import java.io.IOException;  
import org.apache.hadoop.conf.Configuration;  
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;
import org.apache.hadoop.util.Shell;  

public class MyMapReduce {

	// 1.自己的map靜态類
	// 內建Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> 輸入的key,輸入的value,輸出的key,輸出的value
	public static class MyMapper extends Mapper<LongWritable, Text, Text, IntWritable> {

		// 1)、 建立一個IntWritable 類型的對象,給定值為1
		IntWritable iw = new IntWritable(1);
		Text keystr = new Text();

		protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context)
				throws IOException, InterruptedException {

			String line = value.toString();

			// 2)、 傳入每一個map方法的key和value做列印
			System.out.println("key : " + key.get() + "---------- value : " + line);

			String[] strs = line.split(" ");
			
			for (String str : strs) {
				keystr.set(str);
				System.out.println("map 的輸出 = key : ( " + str + ",1 )"  );
				context.write(keystr, iw);
			}
						
			/*StringTokenizer itr = new StringTokenizer(value.toString());
			while (itr.hasMoreTokens()) {
				keystr.set(itr.nextToken());
				context.write(keystr, iw);
			}*/

		}

	}

	// 2.自己的靜态reduce類
	// reduce類的輸入,其實是map類中的map方法的輸出  輸入key,輸出value, 輸出key,輸出value
	public static class MyReduce extends Reducer<Text, IntWritable, Text, IntWritable>{

		IntWritable countWritable = new IntWritable();
		
		//Map類的map方法的資料輸入到Reduce類的group方法中,再到<text,it(1,1)>,再将這個資料輸入到Reduce類的reduce方法中
		@Override
		protected void reduce(Text inputkey, Iterable<IntWritable> inputvalue,
				Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
			// 1).得到key
			String key  = inputkey.toString();
			
			// 2).疊代Iterable,把每個值相加
			int count =  0;
			
			// 3).循環周遊疊代器中的所有值,做相加
			for (IntWritable intWritable : inputvalue) {
				count += intWritable.get();
			}
			
			// 4). 把值設定到IntWritable ,等待輸出
			countWritable.set(count);
			System.out.println("reduce輸出結果 : key = " + key + " , "  + count);
			context.write(inputkey, countWritable);
		}
		
	}

	// 3.運作類:run方法
	/**
	 * 
	 * @param args
	 * @return
	 * @throws Exception
	 */
	public int run(String[] args) throws Exception {  
		  
		//hadoop的配置的上下文
        Configuration configuration = new Configuration();  
  
        //通過上下文,建構一個job執行個體并且傳入任務名稱,單例模式
        Job job = Job.getInstance(configuration, this.getClass().getSimpleName());  
       
        //必須添加,否則本地運作出現問題,伺服器上運作會報錯
        job.setJarByClass(MyMapReduce.class);  
  
        // set job  設定任務從哪裡讀取資料
        // input  調用這個方法的時候,要往args中傳入參數,第一個位置上要傳入從哪裡讀取資料
        Path inpath = new Path(args[0]);  
        FileInputFormat.addInputPath(job, inpath);  
  
        // output  設定任務結果資料儲存到哪裡
        //調用這個方法的時候,要往args中傳入參數,第二個位置要傳入的結果資料儲存到哪裡
        Path outPath = new Path(args[1]);  
        FileOutputFormat.setOutputPath(job, outPath);  
  
        // Mapper  設定 Mapper類的參數
        job.setMapperClass(MyMapper.class);  
        job.setMapOutputKeyClass(Text.class);  
        job.setMapOutputValueClass(IntWritable.class);  
  
        // Reducer  設定 Reducer類的參數
        job.setReducerClass(MyReduce.class);  
        job.setOutputKeyClass(Text.class);  
        job.setOutputValueClass(IntWritable.class);  
  
        // submit job -> YARN  
        boolean isSuccess = job.waitForCompletion(true);  
        return isSuccess ? 0 : 1;  
    }
	
	public static void main(String[] args) throws Exception {  
		  
        args = new String[] {  
                "hdfs://192.168.211.211:8020/test2.txt",  
                "hdfs://192.168.211.211:8020/test2" };  
        // run job  
        int status = new MyMapReduce().run(args);  
  
        System.exit(status);  
    }  

}
           

這樣,再上傳個檔案到hdfs(bin/hdfs dfs -put test2.txt /) 切記必須上傳到hdfs,然後運作!

常見問題:

第一種類型、出現各種空指針:

例如:Exception in thread "main" java.lang.NullPointerException atjava.lang.ProcessBuilder.start(Unknown Source)

An internal error occurred during: "Map/Reducelocation status updater".java.lang.NullPointerException

如果出現這樣的問題,就是上文的配置你沒配置好,好好檢查下!!!!然後在hdfs上建立目錄,上傳檔案試試,如果配置好了,應該不會有這樣的問題

第二種類型、需要修改源碼型:

1、Failed to locate the winutils binary in the hadoop binary path  

java.io.IOException: Could not locate executable 

null

\bin\winutils.exe in the Hadoop binaries.

一開始看到這樣的報錯,我是拒絕的!!這裡其實是因為在Windows下面運作mr代碼必須有個檔案叫做winutil.exe,預設解壓的hadoop的bin目錄下是沒有的,自己下載下傳一個然後放到hadoop目錄的bin當中,程式會根據HADOOP_HOME找到bin目錄下面的winutil.exe,但是有時候其實你都配置好了,它還報這個錯,我就想打爆他的狗頭,這時候就要修改源碼了(看看源碼是哪裡擷取的,你去手動寫一個你正确的路徑)

那麼到底在源碼的哪裡呢?

在hadoop-common-2.7.6.jar這個jar包當中的org.apache.hadoop.util.Shell這個類裡面

Windows下開發hadoop的MapReduce

就是這個屬性,修改下!!

那怎麼改,有個很簡單的方法,Ctrl+A(全選),然後Ctrl+C(複制),把整個類複制下來,然後看下圖!

Windows下開發hadoop的MapReduce

點選畫紅圈的地方,Ctrl+V粘貼進去,他會自動生成想源碼那樣的包,然後直接改這個生成的java類,把377行改成:

Windows下開發hadoop的MapReduce

2、Exception in thread "main"java.lang.UnsatisfiedLinkError:org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z

還有這個幾乎所有人都會遇到的問題,這個其實就是檢查你的檔案系統的時候報的錯

我在我的另一個文章裡有說怎麼修改,就是那個

Hbase在 Windows下運作報錯 IllegalArgumentException:

Pathname /D:/download/repository/org/apache/.....

位址:http://blog.csdn.net/lsr40/article/details/77648012

要修改源碼差不多也就這兩個地方,如果還有别的,請大家在本帖的評論區留言,我研究下~謝謝

第三種類型、修改配置檔案

1、

org.apache.hadoop.security.AccessControlException:

Permissiondenied: user=test, access=WRITE,inode="/user/root/output":root:supergroup:drwxr-xr-x

這裡的問題是權限問題!

兩種解決方法:

第一:使用指令 bin/hdfs dfs -chmod -R 777 / 這個就是将HDFS上面的所有目錄都給777的權限,所有人都可以通路

第二:etc/hadoop下的hdfs-site.xml添加

<property>

<name>dfs.permissions.enabled</name>

<value>false</value>

</property>

然後重新開機hadoop,在運作應該就沒問題了

2、報這個錯誤

Windows下開發hadoop的MapReduce

添加日志檔案,要到linux系統下的hdoop-2.7.6 --> etc --> hadoop下,把 log4j複制到eclipse裡,在eclipse建立一個source Folder 檔案夾,

把日志檔案放進去

Windows下開發hadoop的MapReduce
Windows下開發hadoop的MapReduce

3、

Error: java.lang.RuntimeException: java.lang.ClassNotFoundException:

Class com.ibeifeng.cm.MapReduce$WordMap not found

[java]  view plain  copy

  1. <span style="white-space:pre;">Error: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class com.ibeifeng.cm.MapReduce$WordMap not found  
  2.     at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:1905)  
  3.     at org.apache.hadoop.mapreduce.task.JobContextImpl.getMapperClass(JobContextImpl.java:186)  
  4.     at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:722)  
  5.     at org.apache.hadoop.mapred.MapTask.run(MapTask.java:340)  
  6.     at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:168)  
  7.     at java.security.AccessController.doPrivileged(Native Method)  
  8.     at javax.security.auth.Subject.doAs(Subject.java:422)  
  9.     at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1614)  
  10.     at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:163)  
  11. Caused by: java.lang.ClassNotFoundException: Class com.ibeifeng.cm.MapReduce$WordMap not found  
  12.     at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:1811)  
  13.     at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:1903)  
  14.     ... 8 more</span>  

這個報錯其實很坑的,檢查了好久,看不出來,最後終于找到:

因為建立項目的時候,其實有這個,請看下圖:

Windows下開發hadoop的MapReduce

請注意:這裡隻能添加這3個,如果把yarn-site.xml也copy進來,那樣你運作的時候,就會報如上的錯誤,因為你在mapred-site.xml當中指定了job運作于yarn,(其實你在本地運作的時候,應該是local模式的)你運作的時候,程式去yarn上面找對應的jar,class等資訊,結果沒找到是以。。。

兩種解決方法:

1、把你src/main/resource中,mapred-site.xml這個yarn的值,改成local,就是下圖的這個屬性!!

Windows下開發hadoop的MapReduce

2、把yarn-site.xml和mapred-site.xml這兩個配置檔案從src/main/resource中删除!就不會報這個錯誤了!!

    這是我參考 https://blog.csdn.net/lsr40/article/details/77868113 點選打開連結做的,希望有些幫助

我暫時遇到的問題就是這些,如果大家還有别的報錯,

可以給我留言,互相讨論下,如果有說的不對的地方,請大神批評指出!~

繼續閱讀