windows 10環境下搭建基於Hadoop的Eclipse開發環境

1.1 Hadoop環境配置java

本文用於指導hadoopwindows10環境下單機版使用,軟件版本選擇:node

l Windows10家庭版web

l JDK 1.8.0_171-b11算法

l hadoop-2.7.3apache

1.1.1 Hadoop簡要介紹編程

Hadoop 是Apache基金會下一個開源的分佈式計算平臺,它以分佈式文件系統HDFS和MapReduce算法爲核心,爲用戶提供了系統底層細節透明的分佈式基礎架構。windows

 

1.1.2準備工做

從官網下載Hadoop二進制版本,而後解壓到:D:\Study\codeproject\hadoop-2.7.3服務器

JavaHadoop依賴的運行環境,讀者能夠在Oracle官網獲取最新版的Java版本,因爲只是運行不是開發,因此也能夠只下載JRE。安裝完成後配置安裝完成後,配置JAVA_HOMEJRE_HOME環境變量。執行以下命令表示JDK安裝成功:網絡

C:\Users\45014>java -versionsession

java version "1.8.0_171"

Java(TM) SE Runtime Environment (build 1.8.0_171-b11)

Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)

右鍵單擊個人電腦 –>屬性 –>高級環境變量配置 –>高級選項卡 –>環境變量 –> 單擊新建HADOOP_HOME接着編輯環境變量path,將hadoopbin目錄加入到後面

1.1.2 修改Hadoop配置

編輯D:\Study\codeproject\hadoop-2.7.3\etc\hadoop」下的core-site.xml文件

 <configuration>

    <property>

        <name>hadoop.tmp.dir</name>

        <value>/D:/Study/codeproject/hadoop-2.7.3/data/temp</value>

    </property>

    <property>

        <name>dfs.name.dir</name>

        <value>/D:/Study/codeproject/hadoop-2.7.3/data/name</value>

    </property>

    <property>

        <name>fs.default.name</name>

        <value>hdfs://localhost:9000</value>

    </property>

    <property>

        <name>fs.defaultFS</name>

        <value>hdfs://localhost:9000</value>

    </property>

</configuration>

 

編輯D:\Study\codeproject\hadoop-2.7.3\etc\hadoop」下的mapred-site.xml文件

<configuration>

    <property>

       <name>mapreduce.framework.name</name>

       <value>yarn</value>

    </property>

    <property>

       <name>mapred.job.tracker</name>

       <value>hdfs://localhost:9001</value>

    </property>

</configuration>

編輯D:\Study\codeproject\hadoop-2.7.3\etc\hadoop」下的hdfs-site.xml文件

<configuration>

 <property>

        <name>dfs.replication</name>

        <value>1</value>   <!-- 這個參數設置爲1,由於是單機版hadoop -->

    </property>

    <property>

        <name>dfs.namenode.name.dir</name>

        <value>/D:/Study/codeproject/hadoop-2.7.3/data/namenode</value>

    </property>

    <property>

        <name>dfs.datanode.data.dir</name>

        <value>/D:/Study/codeproject/hadoop-2.7.3/datanode</value>

    </property>

        <property>

        <name>dfs.data.dir</name>

        <value>/D:/Study/codeproject/hadoop-2.7.3/datanode</value>

    </property>

</configuration>

編輯D:\Study\codeproject\hadoop-2.7.3\etc\hadoop」下的yarn-site.xml文件

<configuration>

    <property>

       <name>yarn.nodemanager.aux-services</name>

       <value>mapreduce_shuffle</value>

    </property>

    <property>

       <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>

       <value>org.apache.hadoop.mapred.ShuffleHandler</value>

    </property>

</configuration>

 

1.1.3 啓動Hadoop

(1)進入D:\Study\codeproject\hadoop-2.7.3\bin目錄,格式化hdfscmd中運行命令 hdfs namenode -format

(2)運行cmd窗口,切換到hadoopsbin目錄,執行「start-all.cmd」,它將會啓動如下進程。

 

1.1.4 訪問Hadoop管理界面

啓動成功後,進入資源管理GUI:http://localhost:8088/

 

節點管理GUI:http://localhost:50070/

 

1.2 Eclipse操做Hadoop環境配置

1.eclipse上安裝Hadoop插件

把下載好的hadoop-eclipse-plugin-2.7.1.jar文件拷貝到eclipse安裝目錄中的plugins文件夾內(注意版本選擇,不然可能致使不可用)。以下圖:

 

2.繼續配置hadoop編譯環境(方便配置,確保已經啓動了 Hadoop

啓動 Eclipse 後就能夠在左側的Project Explorer中看到DFS Locations

 

3.插件的配置

第一步:選擇 Window 菜單下的 Preference

此時會彈出一個窗體,點擊選擇 Hadoop Map/Reduce 選項,選擇 Hadoop 的安裝目錄(例如:/home/hadoop/hadoop)。

第二步:切換 Map/Reduce 開發視圖

選擇Window 菜單下選擇 Open Perspective -> Other,彈出一個窗體,從中選擇Map/Reduce 選項便可進行切換。

第三步:創建與 Hadoop 集羣的鏈接

點擊Eclipse軟件右下角的Map/Reduce Locations 面板,在面板中單擊右鍵,選擇New Hadoop Location

在彈出來的General選項面板中,General的設置要與 Hadoop 的配置一致。通常兩個 Host值是同樣的,若是是僞分佈式,填寫 localhost 便可,這裏使用的是Hadoop僞分佈,設置fs.defaultFS hdfs://localhost:9000,則 DFS Master Port 改成 9000Map/Reduce(V2) Master Port 用默認的便可,Location Name 隨意填寫。

 

1.3 上傳文件到HDFS

HDFS是Hadoop體系中數據存儲管理的基礎。 HDFS採用主從(Master/Slave)結構模型,一個HDFS集羣是由一個NameNode和若干個DataNode組成的。NameNode做爲主服務器,管理文件系統命名空間和客戶端對文件的訪問操做。DataNode管理存儲的數據。

1.運行cmd窗口,執行hdfs namenode -format

根據你core-site.xml的配置,接下來你就能夠經過:hdfs://localhost:9000來對hdfs進行操做了。

1.建立輸入目錄

C:\Users\45014>hadoop fs -mkdir hdfs://localhost:9000/user/

C:\Users\45014>hadoop fs -mkdir hdfs://localhost:9000/user/wcinput

2.上傳數據到目錄

C:\Users\45014>hadoop fs -put D:\file1.txt hdfs://localhost:9000/user/wcinput

C:\Users\45014>hadoop fs -put D:\file2.txt hdfs://localhost:9000/user/wcinput

3.查看文件

C:\Users\45014>hadoop fs -ls hdfs://localhost:9000/user/wcinput

Found 2 items

-rw-r--r--   1 45014 supergroup         52 2019-03-08 22:48 hdfs://localhost:9000/user/wcinput/file1.txt

-rw-r--r--   1 45014 supergroup         13 2019-03-08 22:48 hdfs://localhost:9000/user/wcinput/file2.txt

在esclipse界面的DFS Locations右鍵點擊refresh,以下圖:

 

 

1.4 Map/Reducehello world

  MapReduce是Google的一項重要技術,它是一個編程模型,用以進行大數據量的計算。對於大數據量的計算,一般採用的處理手法就是並行計算。至少現階段而言,對許多開發人員來講,並行計算仍是一個比較遙遠的東西。MapReduce就是一種簡化並行計算的編程模型,它讓那些沒有多少並行計算經驗的開發人員也能夠開發並行應用。

下面代碼來自網絡,一塊兒參考學習。

import java.io.IOException;
import java.util.StringTokenizer;
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.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;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;

@SuppressWarnings("unused")
public class WordCount
{

    public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>
    // 爲何這裏k1要用Object、Text、IntWritable等,而不是java的string啊、int啊類型,
    //固然,你能夠用其餘的,這樣用的好處是,由於它裏面實現了序列化和反序列化。
    // 可讓在節點間傳輸和通訊效率更高。這就爲何hadoop自己的機制類型的誕生。

    // 這個Mapper類是一個泛型類型,它有四個形參類型,分別指定map函數的輸入鍵、輸入值、輸出鍵、輸出值的類型。
    //hadoop沒有直接使用Java內嵌的類型,而是本身開發了一套能夠優化網絡序列化傳輸的基本類型。
    // 這些類型都在org.apache.hadoop.io包中。
    // 好比這個例子中的Object類型,適用於字段須要使用多種類型的時候,Text類型至關於Java中的String類型,
    //IntWritable類型至關於Java中的Integer類型
    {
        // 定義兩個變量或者說是定義兩個對象,叫法均可以
        private final static IntWritable one = new IntWritable(1);// 這個1表示每一個單詞出現一次,map的輸出value就是1.
        // 由於,v1是單詞出現次數,直接對one賦值爲1
        private Text word = new Text();

        public void map(Object key, Text value, Context context)
                // context它是mapper的一個內部類,簡單的說頂級接口是爲了在map或是reduce任務中跟蹤task的狀態,很天然的MapContext就是記錄了map執行的上下文,在mapper類中,這個context能夠存儲一些job
                // conf的信息,好比job運行時參數等,
                // 咱們能夠在map函數中處理這個信息,這也是Hadoop中參數傳遞中一個很經典的例子,同時context做爲了map和reduce執行中各個函數的一個橋樑,這個設計和Java
                // web中的session對象、application對象很類似
                // 簡單的說context對象保存了做業運行的上下文信息,好比:做業配置信息、InputSplit信息、任務ID等
                // 咱們這裏最直觀的就是主要用到context的write方法。
                // 說白了,context起到的是鏈接map和reduce的橋樑。起到上下文的做用!

                throws IOException, InterruptedException
        {
            // The tokenizer uses the default delimiter set, which is " \t\n\r": the space
            // character, the tab character, the newline character, the carriage-return
            // character
            StringTokenizer itr = new StringTokenizer(value.toString());// 將Text類型的value轉化成字符串類型

            while (itr.hasMoreTokens())
            {
                // 實際上就是java.util.StringTokenizer.hasMoreTokens()
                // 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
        {
            // 咱們這裏最直觀的就是主要用到context的write方法。
            // 說白了,context起到的是鏈接map和reduce的橋樑。起到上下文的做用!

            int sum = 0;
            for (IntWritable val : values)
            {// 叫作加強的for循環,也叫for星型循環
                sum += val.get();
            }
            result.set(sum);
            context.write(key, result);
        }
    }

    public static void main(String[] args) throws Exception
    {
        Configuration conf = new Configuration();// 程序裏,只需寫這麼一句話,就會加載到hadoop的配置文件了
        // Configuration類表明做業的配置,該類會加載mapred-site.xml、hdfs-site.xml、core-site.xml等配置文件。

        // 刪除已經存在的輸出目錄
        Path mypath = new Path("hdfs://localhost:9000/user/wcoutput");// 輸出路徑
        FileSystem hdfs = mypath.getFileSystem(conf);// 程序裏,只需寫這麼一句話,就能夠獲取到文件系統了。
        
        // 若是文件系統中存在這個輸出路徑,則刪除掉,保證輸出目錄不能提早存在。
        if (hdfs.isDirectory(mypath))
        {
            hdfs.delete(mypath, true);
        }

        // job對象指定了做業執行規範,能夠用它來控制整個做業的運行。
        Job job = Job.getInstance();// new Job(conf, "word count");
        
        job.setJarByClass(WordCount.class);// 咱們在hadoop集羣上運行做業的時候,要把代碼打包成一個jar文件,而後把這個文件
        // 傳到集羣上,而後經過命令來執行這個做業,可是命令中沒必要指定JAR文件的名稱,在這條命令中經過job對象的setJarByClass()中傳遞一個主類就行,
        //hadoop會經過這個主類來查找包含它的JAR文件。

        job.setMapperClass(TokenizerMapper.class);
        // job.setReducerClass(IntSumReducer.class);
        job.setCombinerClass(IntSumReducer.class);// Combiner最終不能影響reduce輸出的結果


        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        // 通常狀況下mapper和reducer的輸出的數據類型是同樣的,因此咱們用上面兩條命令就行,若是不同,咱們就能夠用下面兩條命令單獨指定mapper的輸出key、value的數據類型
        // job.setMapOutputKeyClass(Text.class);
        // job.setMapOutputValueClass(IntWritable.class);
        // hadoop默認的是TextInputFormat和TextOutputFormat,因此說咱們這裏能夠不用配置。
        // job.setInputFormatClass(TextInputFormat.class);
        // job.setOutputFormatClass(TextOutputFormat.class);

        FileInputFormat.addInputPath(job, new Path("hdfs://localhost:9000/user/wcinput/file1.txt"));// FileInputFormat.addInputPath()指定的這個路徑能夠是單個文件、一個目錄或符合特定文件模式的一系列文件。
        // 從方法名稱能夠看出,能夠經過屢次調用這個方法來實現多路徑的輸入。
        FileOutputFormat.setOutputPath(job, new Path("hdfs://localhost:9000/user/wcoutput"));// 只能有一個輸出路徑,該路徑指定的就是reduce函數輸出文件的寫入目錄。
        // 特別注意:輸出目錄不能提早存在,不然hadoop會報錯並拒絕執行做業,這樣作的目的是防止數據丟失,由於長時間運行的做業若是結果被意外覆蓋掉,那確定不是咱們想要的
        System.exit(job.waitForCompletion(true) ? 0 : 1);
        // 使用job.waitForCompletion()提交做業並等待執行完成,該方法返回一個boolean值,表示執行成功或者失敗,這個布爾值被轉換成程序退出代碼0或1,該布爾參數仍是一個詳細標識,因此做業會把進度寫到控制檯。
        // waitForCompletion()提交做業後,每秒會輪詢做業的進度,若是發現和上次報告後有改變,就把進度報告到控制檯,做業完成後,若是成功就顯示做業計數器,若是失敗則把致使做業失敗的錯誤輸出到控制檯
    }
}

 

 

 

相關文章
相關標籤/搜索