1. 程式人生 > >hadoop實踐(五)win10+eclipse+hadoop2.6.4 開發環境

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