寫在前面
最近在做大數據項目,首先就是配置Hadoop集羣,之後就是通過IDEA來連接虛擬機中搭建好的HDFS,但是由於是mac系統,而且網絡上面IDEA的配置教程相比於eclipse來說大多都不詳細清楚,所以遇到了很多的坑,解決問題之後把相關的過程和方法寫下來供交流參考。
配置虛擬機Hadoop集羣
這個網上有很多的教程,我就不寫了
在mac上面配置Hadoop 環境
這裏建議把之前在linux上面配置好的Hadoop文件夾直接從虛擬機上面傳出來,這樣既省事又可以避免出錯,畢竟配置環境還是比較複雜的。從虛擬機上面導出來之後,可以開始配置mac的Hadoop環境變量了。
終端輸入命令:
sudo vim .bash_profile
在其中的空閒位置處寫下環境變量,這裏HADOOP_HOME是你從虛擬機中導出來的Hadoop文件路徑,我的在/Volumes/Al的擴展/Hadoop/hadoop-2.7.7
,我配置了HADOOP_USER_NAME=root
是爲了等會要跑程序的用戶是root用戶。
#hadoop
export HADOOP_HOME=/Volumes/Al的擴展/Hadoop/hadoop-2.7.7
export HADOOP_USER_NAME=root
export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin
之後保存文件,然後
source .bash_profile
這時在mac終端上輸入hadoop就可以看到這樣的信息
這樣就算成功啦!
在IDEA中使用Hadoop的插件
插件的代碼地址:https://github.com/fangyuzhong2016/HadoopIntellijPlugin
如果下載不到的老哥也可以從下面這個鏈接下載
鏈接:https://pan.baidu.com/s/1qRBia2dJvCeZbon8q5edHQ 密碼:td8r
下載之後要進行編譯,需要電腦有maven3環境和1.8的jdk,只能是1.8!上面有講下載下來需要在裏面改hadoop版本爲本機hadoop版本,但是我沒改也可以使用,
把這個zip下載下來之後,打開IDEA,創建maven項目,然後使用“command + ,“
來打開Preferences,找到裏面的Plugin插件設置
點擊上方的齒輪,選擇從硬盤安裝
找到你下載的安裝包的位置
點擊open,會顯示這個
這時候OK就可以了,這時候重啓一下IDEA,就會發現右上角多了個Hadoop的選項。這裏選擇設置
連接名稱隨便寫,描述隨便寫,下面兩個地址要填虛擬機中的那臺master機的ip地址,第一個端口是虛擬機配置Hadoop的時候可以得到的,第二個端口寫9000。不要點擊下面的測試,是不可能成功的,直接點擊確定。
然後你會發現在IDEA的最左側多了一個黃色的小象,點開它,如果可以成功連接上的話,可以看到你hdfs中的文件
但是他不如eclipse上面對應的插件好用,刷新沒有那麼快,可能有些時候需要手動一下。至此我們成功連接上虛擬機中的HDFS
配置MAVEN項目來運行我們第一個MapReduce程序
一開始不知道maven項目可以直接自動導入依賴,按照網上的教程一個一個從我的hadoop文件裏面吧jar包導入進去,給我累壞了,後來改了項目中的pom.xml文件才知道,直接從阿里雲的maven倉庫自動導入依賴。修改項目中的pom.xml文件,把groupId和artifactId改成自己的,添加阿里雲的倉庫,並且加入slf4的日誌輸出:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.Al</groupId>
<artifactId>HadoopTest2</artifactId>
<version>1.0-SNAPSHOT</version>
<repositories>
<repository>
<id>aliyun</id>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
</repositories>
<properties>
<hadoop.version>2.7.7</hadoop.version>
</properties>
<dependencies>
<!-- 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-common</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-jobclient</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-common</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.26</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.4</version>
</dependency>
</dependencies>
</project>
剛把這些內容複製進去的時候會發現他們是紅色的字體,因爲jar包沒有導入進來,這時候看IDEA的右下角你會發現他在飛快的導包,過一會完成了我們的字體也就恢復常規顏色了。這時我們使用hadoop的包就不會報錯了。之後要在resource文件夾中配置log4j
log4j.rootLogger=INFO, stdout, R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log
log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
現在開始寫我們第一個WordCount小程序吧!新建一個JAVA類,然後把下面的代碼粘貼上去。(代碼不是本人的,部分註釋是)
package com.Al;
import java.io.IOException;
import java.util.Arrays;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
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.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
/**
* 統計文本中單詞出現的次數 以文件形式輸出
*
* @author lyd
*/
public class MyWordCount {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//1.設置conf對象,並配置hdfs路徑
//2.設置job對象,在job對象中設置 Jar map reduce reduce的輸出類型(key value) 輸出格式化方式
//文件的輸入和輸出路徑 系統退出
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://master:9000"); //設置成集羣的key,我的是fs.defaultFS,value是上一步配的hdfs的地址
Job job = Job.getInstance(conf, "wordcount");
job.setJarByClass(MyWordCount.class);
job.setMapperClass(MyMapper.class);
job.setReducerClass(MyReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
job.setInputFormatClass(TextInputFormat.class);
FileInputFormat.addInputPath(job, new Path("/222.txt")); //設置成你要轉換的文本,我這裏是222.txt,要在hdfs中存在
Path outputPath = new Path("/wordcount/");
FileSystem.get(conf).delete(outputPath, true);// 檢查是否存在輸出路徑,如果存在就先刪除
FileOutputFormat.setOutputPath(job, outputPath);
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
/**
* @param KEYIN →k1 表示每一行的起始位置(偏移量offset)
* @param VALUEIN →v1 表示每一行的文本內容
* @param KEYOUT →k2 表示每一行中的每個單詞
* @param VALUEOUT →v2 表示每一行中的每個單詞的出現次數,固定值爲1
* @author lyd
* @version 1.0
*/
//Mapper中第三個和第四個參數必須和Reducer中第一個和第二個參數相同,輸出結果<key, {value}>
public static class MyMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context)
throws IOException, InterruptedException {
System.err.println("key的值爲:" + key.toString());
System.err.println("value的值爲:" + value.toString());
String[] words = value.toString().split("\\s+");
System.out.println(Arrays.toString(words) + "-_-");
IntWritable one = new IntWritable(1);
Text text = new Text();
for (String word : words) {
System.out.println("------------->" + word);
text.set(word);
context.write(text, one); //連接map和reduce的context
}
}
}
/**
* @param KEYIN →k2 表示每一行中的每個單詞
* @param VALUEIN →v2 表示每一行中的每個單詞的出現次數,固定值爲1
* @param KEYOUT →k3 表示每一行中的每個單詞
* @param VALUEOUT →v3 表示每一行中的每個單詞的出現次數之和
* @author lyd
* @version 1.0
*/
public static class MyReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
@Override
protected void reduce(Text value, Iterable<IntWritable> iterable,
Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
int sum = 0;
IntWritable i = new IntWritable();
System.err.println("value的值爲:" + value + " end!");
for (IntWritable intWritable : iterable) {
System.err.println("===>" + intWritable + "<====");
sum += intWritable.get();
}
i.set(sum);
context.write(value, i);
}
}
}
這時候點擊main方法旁邊的綠色箭頭來運行程序,可以看到程序成功執行,
稍等一會我們會在hdfs裏面發現多了一個wordcount文件夾
SUCCESS是成功執行的標誌,下面那個文件就是我們最後的結果,我們可以在項目的data文件夾中同步找到這個文件,看一下程序輸出的結果吧。
到此爲止就全部結束啦!希望能對你有幫助哦~