【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