1. 程式人生 > >【Hadoop】Windows 10 在Intellij IEDA本地執行Hadoop MapReduce例項

【Hadoop】Windows 10 在Intellij IEDA本地執行Hadoop MapReduce例項

環境:
作業系統:Windows 10
Hadoop版本:2.7.3
Java版本: 1.8

前期準備:

1. 配置hadoop環境。

2. 配置maven環境。

1.下載maven部署包apache-maven-3.5.3-bin.zip,解壓到D:\envpath\apache-maven目錄下。
2.在apache-maven目錄下新建資料夾repository,這個資料夾用來存放maven下載的jar包。
3.修改apache-maven-3.5.3-bin的conf資料夾下settings.xml檔案。將修改的settings.xml檔案複製到apache-maven目錄下。
<mirrors><mirrors>

用來配置映象地址,可以加快依賴的下載。
<localRepository><localRepository>用來配置存放依賴檔案的本地目錄。

<?xml version="1.0" encoding="UTF-8"?>
  <localRepository>D:/envpath/apache-maven/repository</localRepository>
  <mirrors>
    <mirror>
            <id>alimaven</id>
            <mirrorOf
>
central</mirrorOf> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> </mirror> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url
>
http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> <mirror> <id>central</id> <name>Maven Repository Switchboard</name> <url>http://repo1.maven.org/maven2/</url> <mirrorOf>central</mirrorOf> </mirror> <mirror> <id>repo2</id> <mirrorOf>central</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>http://repo2.maven.org/maven2/</url> </mirror> <mirror> <id>ibiblio</id> <mirrorOf>central</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>http://mirrors.ibiblio.org/pub/mirrors/maven2/</url> </mirror> <mirror> <id>jboss-public-repository-group</id> <mirrorOf>central</mirrorOf> <name>JBoss Public Repository Group</name> <url>http://repository.jboss.org/nexus/content/groups/public</url> </mirror> <mirror> <id>google-maven-central</id> <name>Google Maven Central</name> <url>https://maven-central.storage.googleapis.com </url> <mirrorOf>central</mirrorOf> </mirror> <!-- 中央倉庫在中國的映象 --> <mirror> <id>maven.net.cn</id> <name>oneof the central mirrors in china</name> <url>http://maven.net.cn/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors> <profiles> </profiles> </settings>

4.配置系統環境變數。
1) 變數名:MAVEN_HOME 變數值:D:/envpath/apache-maven/repository(maven包的目錄)
2) 變數名:MAVEN_OPTS 變數值:-Xms128m -Xmx512m -Duser.language=zh -Dfile.encoding=UTF-8
3) 將%MAVEN_HOM%bin加入Path變數。
4.測試maven是否配置成功。在cmd輸入mvn -v。如下,表示成功。

C:\Users\DELL_PC>mvn -v
Apache Maven 3.5.3 (3383c37e1f9e9b3bc3df5050c29c8aff9f295297; 2018-02-25T03:49:05+08:00)
Maven home: D:\envpath\apache-maven\apache-maven-3.5.3\bin\..
Java version: 1.8.0_111, vendor: Oracle Corporation
Java home: D:\envpath\jdk1.8.0_111\jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

3. 在idea建立Maven工程

1.配置idea的maven。
開啟file-Settings,搜尋maven。idea預設使用內嵌的maven。如下,將maven的home目錄改為為本地的maven目錄,settings.xml和repository也一併修改。
這裡寫圖片描述
開啟idea,建立project時,選擇建立maven工程。
這裡寫圖片描述
工程建立好後會有一個pom.xml檔案。在pom.xml檔案中新增hadoop所需的依賴。如果不知道依賴該怎麼寫,可以直接到MVNRepository搜尋。選擇相應的版本,直接複製。
這裡寫圖片描述
提供一個樣例,如下所示。

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-core -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-core</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.7.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>2.7.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-mapreduce-client-core -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-core</artifactId>
            <version>2.7.3</version>
        </dependency>

    </dependencies>

2.執行MR例項

1.編寫JavaWordCount

新建一個java原始檔,例項為WordCount,輸入檔案為data/input/wc.txt,data資料夾在工程的根目錄下。

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;

public class JavaWordCount {
    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 {
        System.setProperty("hadoop.home.dir", "D:\\envpath\\hadoop-2.7.3");
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf, "word count");
        job.setJarByClass(JavaWordCount.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("data/input/wc.txt"));//設定輸入路徑

        FileOutputFormat.setOutputPath(job,
                new Path("data/output/wc"));//設定輸出路徑
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

3. 執行問題解決

直接執行上述程式碼,發現遇到了很多問題。按發生的順序依次記錄。

1. NativeIO問題

具體表現:找不到org.apache.hadoop.io.nativeio.NativeIO&POSIX&Stat
1)按照網上的一些解決方法,將hadoop目錄下的bin檔案中的hadoop.dll和winutils.exe複製到c:\windows\System32。注意,從官網下載的hadoop的部署包是沒有這兩個檔案的,只能通過其他途徑找到相應hadoop版本的hadoop.dll和winutils.exe檔案。
2)再次執行,還是無法解決。於是,重啟。
3)重啟後還是無法解決。又將其複製到了C:\Windows\SysWOW64。
4)還是無法解決,可能是hadoop.dll等檔案版本不適配。於是,直接下載hadoop-2.7.3的原始碼檔案。在maven工程中建立package,package與NativeIO.java的一致,為org.apache.hadoop.io.nativeio。將NativeIO.java複製到該目錄下。
5)如果出現其他的無法找到的類的問題,也可以用這個方法解決。

2.FileUtils問題

具體表現:Exception in thread “main” java.io.IOException: Failed to set permissions of path: \tmp\hadoop-XXX\mapred\staging\XXX-XXX.staging to 0700
1)在maven工程建立org.apache.hadoops.fs的package,將FileUtils.java檔案複製到該目錄下,將checkReturnedValue內的程式碼註釋掉。

private static void checkReturnValue(boolean rv, File p, 
                                       FsPermission permission
                                       ) throws IOException {
    /*
    if (!rv) {
      throw new IOException("Failed to set permissions of path: " + p + 
                            " to " + 
                            String.format("%04o", permission.toShort()));
    }
    */
  }

2)編譯工程。在工程的target目錄下得到FileUtils.class檔案。
3)在maven的respository目錄搜尋hadoop-core,搜尋到hadoop-core-1.2.1.jar。解壓這個jar檔案。用新編譯的FileUtils.class檔案代替jar中相應的檔案。然後,打包jar。可以通過cmd命令打包jar。

jar cvf hadoop-core-1.2.1.jar /hadoop-core-1.2.1

4)新打包的jar替換掉原來的jar包。問題解決。

3. 每次Maven import changes後Java版本變1.5

具體表現,每次更新pom.xml檔案,import changes後,專案的language level變成1.5(雖然配置的jdk是1.8)。build後,會出現如下錯誤。

Error:(732, 9) java: -source 1.5 中不支援 try-with-resources
  (請使用 -source 7 或更高版本以啟用 try-with-resources)

一個比較笨的方法是,每次import changes後去setting和project structure改變java bytecod version和language level。
這裡寫圖片描述
這裡寫圖片描述
另一種就是在pom.xml新增設定。

<plugins>
    <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-compiler-plugin</artifactId>
       <version>3.1</version>
       <configuration>
           <source>1.8</source>
           <target>1.8</target>
       </configuration>
    </plugin>
</plugins>

4.某一個依賴下的類都找不到

檢視pom.xml是否設定錯誤。相應依賴下是否設定了<scope>provided</scope>
比如下面這個例子,會導致hadoop-common包含類都找不到類。解決這個問題只需要將scope的定義去掉。

  <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.3</version>
            <scope>provided</scope>
  </dependency>

5.無log資訊

具體表現:log4j:WARN No appenders could be found for logger (org.apache.hadoop.metrics2.lib.MutableMetricsFactory).
解決:在src的resources資料夾下新建一個log4j.properties。在檔案中新增如下內容。

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/hadoop.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n