hadoop實踐(五)win10+eclipse+hadoop2.6.4 開發環境
本人環境為win10(才從win7升級)
eclipse是 Kepler Service Release 1
在win10下,安裝了vm workstation,其上安裝了centos6.5 ,並在上面部署了hadoop2.6.4的偽分散式安裝
一、 目標
設定win10下的eclipse開發環境,並且可以在此環境上開發hadoop應用,並在偽分散式hadoop環境下測試。
二、準備
1、eclipse ( Kepler Service Release 1)
2、 hadoop2.6.4
3、 hadoop.dll 和 winutils
4、 wordcount 程式碼
5、 wordcount 所需要的統計單詞的文字源
6、 hadoop for eclipse的外掛,本人使用的外掛為 hadoop-eclipse-plugin-2.6.4.jar
三、環境搭建步驟
1、 將hadoop2.6.4解壓 在win10系統的任意目錄下。 (就是為了配置eclipse用,實際聯調的時候,是連線linux 虛機上的偽分散式hadoop)
2、 設定win10的環境變數,通過控制面板-》系統-》高階設定-》環境變數 需要設定如下幾個環境變數,已本人機器為例:
JAVA_HOME=C:\Program Files (x86)\Java\jre6\bin
HADOOP_HOME=E:\cwqwork\develop\hadoop-2.6.4
path 增加最後 E:\cwqwork\develop\hadoop-2.6.4\bin
3、拷貝外掛到 eclipse安裝目錄下的plugsin目錄
4、 啟動eclipse, windows-》hadoop Map/Reduce
在 hadoop installation directory 裡面,填入 前面第1步解壓的目錄,點選OK
5、 介面最右邊新出先的 Map/Reduce標籤點中, 在最左邊Project Explorer 會出現 DFS Locations。
介面最右下角有個藍色小象,點選後,設定 hadoop location
6、上面設定好後,就可以 一層一層瀏覽 DFS Locations。 這裡顯示的是 linux下hadoop的dfs系統
四、 測試工程程式碼
1、 新建工程,選other -》map reduce project, 然後輸入工程名稱等等,建立新的工程
2、 建立 WordCount 類
程式碼如下:
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
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;
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();
//conf.set("mapred.job.tracker","192.168.136.155:9001" );
//conf.set("fs.default.name","192.168.136.155:9000" );
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
if (otherArgs.length != 2) {
System.err.println("Usage: wordcount <in> <out>");
System.exit(2);
}
System.out.println ("Usage: wordcount <in> <out>" + otherArgs[0] +" "+ otherArgs[1] );
Job job = new Job(conf, "wordcount");
job.setJarByClass(WordCount.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.out.println ("add input path:" + otherArgs[0]);
System.out.println ("set output path:" + otherArgs[1]);
System.out.println ("begin wait job completion");
job.waitForCompletion(true);
}
}
建立完成後, 在linux 虛機上匯入需要統計的文字
文字1:Hello world Hello me! cwq solo
文字2: Hello world Hello you! solo
在linux 目錄 /opt/hadoop/input/wordcount 下:
echo "Hello world Hello me! cwq solo" >test1.txt
echo " Hello world Hello you! solo" >test2.txt
hadoop fs -put /opt/hadoop/input/wordcount input
3、 完成後,在類上右鍵-》run configuration-》 輸入引數
hdfs://192.168.136.155:9000/user/hadoop/input/wordcount hdfs://192.168.136.155:9000/user/hadoop/output/wordcount
輸入後,不要執行。
然後,用run on hadoop 方式執行。
4、 正常情況下,會報異常:
Exception in thread "main" java.lang.NullPointerException
at java.lang.ProcessBuilder.start(ProcessBuilder.java:441)
at org.apache.hadoop.util.Shell.runCommand(Shell.java:445)
at org.apache.hadoop.util.Shell.run(Shell.java:418)
原因是,沒有安裝補丁。 將 hadoop.dll 和 winutils 拷貝到 win10上hadoop目錄下bin目錄。
5、 再次執行,沒有異常,但是執行結束,檢視dfs 沒有output結果, console沒有輸出異常。 這裡糾結很久。
解決辦法:在src 目錄下,建立log.properities檔案,使得log4j 可以列印
log4j.rootLogger=debug,stdout,R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p - %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=mapreduce_test.log
log4j.appender.R.MaxFileSize=1MB
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%
log4j.logger.com.codefutures=DEBUG
6、再次執行,console列印會有error
WARN - job_local194089354_0001
org.apache.hadoop.security.AccessControlException: Permission denied: user=Administrator, access=WRITE, inode="/user/hadoop/output":hadoop:supergroup:drwxr-xr-x
at org.apache.hadoop.hdfs.server.namenode.FSPermissionChecker.checkFsPermission(FSPermissionChecker.java:271)
說明是許可權問題, eclipse是用Administrator啟動的,連線linux下的hadoop是用此使用者,所以許可權禁止。
解決辦法:
1)、如果是測試環境,可以取消hadoop hdfs的使用者許可權檢查。開啟conf/hdfs-site.xml,找到dfs.permissions屬性修改為false(預設為true)OK了。
2)、修改hadoop location引數,在advanced parameter選項卡中,找到hadoop.job.ugi項,將此項改為啟動hadoop的使用者名稱即可
3)、 修改window 機器的使用者名稱為 hadoop 使用者名稱。
7、執行,這次正確執行完成,console 不報告錯誤, dfs location 右鍵 -》reconnect -》一層一層點開,最後output 目錄下看到統計單詞結果。
Hello4
cwq1
me!1
solo2
world2
you!1