構建Hadoop偽分散式環境

BruceZhang發表於2015-10-13

構建Hadoop偽分散式環境

  這篇文章介紹Hadoop偽分散式環境的搭建過程與原理,是個人的學習總結,以紀念在各個步驟中遇到的麻煩、踩過的坑!

  這篇筆記包含這樣幾個內容:

  • 配置偽分散式環境

  • 執行一個簡單的作業

  • 可能遇到的問題及解決辦法

配置偽分散式環境

  本文中的內容基於Hadoop2,即MapReduce作業執行在Yarn平臺之上。

  • 打通SSH,實現無密碼登陸
      由於Hadoop控制指令碼需要登陸到叢集中的Slave節點執行操作(比如,啟動守護程式),如果每一次登入都輸入密碼,顯然不是個好辦法。叢集中的做法是設定一對祕鑰,叢集中的節點都能共享。在偽分散式環境下,採用更簡單的做法,設定一個空的密碼就行了。
      需要執行下面的Shell命令:
$ cd ~/.ssh/
$ ssh-keygen -t rsa  # 空口令
$ cat id_rsa.pub >> authorized_keys  # 加入授權
  • Hadoop配置檔案
      我們會在 /hadoop/ect/hadoop 目錄下看到一大堆xml配置檔案,我們需要關注和修改的有下面這麼幾個 :
      1. etc/hadoop/core-site.xml
      這個是Hadoop的核心配置檔案,預設是空的,是Hadoop叢集的全域性配置,我們在配置偽分散式環境的時候需要這樣簡單的設定 :
<configuration>
    <property>
        <name>hadoop.tmp.dir</name>
        <value>file:/usr/local/hadoop/tmp</value>
    </property>
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://localhost:8020</value>
    </property>
</configuration>

  2. etc/hadoop/hdfs-site.xml
  根據名字,我們知道它是用來配置分散式作業系統的,包含了副本的個數,namenode和datanode的位置,由於,偽分散式環境仍然只是一臺機器,所以,我們需要把副本的個數限制為1,配置如下:

<configuration>
    <property>
        <name>dfs.replication</name>
        <value>1</value>
    </property>
    <property>
        <name>dfs.namenode.name.dir</name>
        <value>file:/usr/local/hadoop/tmp/dfs/name</value>
    </property>
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>file:/usr/local/hadoop/tmp/dfs/data</value>
    </property>
</configuration>

  3. etc/hadoop/mapred-site.xml
  雖然在Yarn平臺上,不再有JobTracker和TaskTracker了,但是,我們仍然需要配置mapred-site,當然,不再是指定原先的那兩個守護程式的host了,而是設定MapReduce的執行平臺,我們使用的是Yarn平臺,那麼,按照下面這樣設定:

<configuration>
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
</configuration>

  4. etc/hadoop/yarn-site.xml
  Yarn平臺上設計了資源管理器和節點管理器,我們在這個配置檔案中就需要去配置,另外,由於沒有了TaskTracker,那麼map的輸出傳遞到reduce就需要一個輔助的service – mapreduce_shuffle, 配置如下:

<configuration>
    <!-- 指定ResourceManager節點的主機名 -->
    <property>
        <name>yarn.resourcemanager.hostname</name>
        <value>localhost</value>
    </property>
    <!-- reducer獲取資料的方式 -->
    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>
</configuration>
  • 開啟守護程式
      我們需要這個幾個守護程式 :
      NameNode
      DataNode
      SecondaryNameNode
      NodeManager
      ResourceManager

NameNode需要我們自己手動的進行格式化操作,DataNode則不需要,在初始化階段會自動建立,我們需要執行

/hadoop/bin/hdfs namenode -format

接下來,啟動分散式檔案系統HDFS:

/hadoop/sbin/start-dfs.sh

然後,開啟Yarn管理平臺:

/hadoop/sbin/start-yarn.sh

  到這裡,我們的偽分散式環境就搭建好了,下面,我們執行一個簡單的作業,這裡只是敘述執行方法,並不對作業本身進行描述。

執行一個簡單的作業

  最好使用一個自己比較熟悉的IDE,並安裝合適的構建工具外掛,我這裡使用的IDE是Intellij,構建工具是Maven。之後,我們編寫Map和Reduce程式,並寫好作業驅動程式,然後,利用構建工具打包,比如,Maven的方式:

mvn -U clean package

  之後,執行hadoop命令執行作業:

hadoop jar {your_job}.jar {your_package}.ClassName {target}/input {target}/output

  執行了這條語句之後,我們應該能看到類似下面的進度和計數器輸出:

15/10/13 15:15:01 INFO mapreduce.Job: Running job: job_1444655578016_0003
15/10/13 15:15:07 INFO mapreduce.Job: Job job_1444655578016_0003 running in uber mode : false
15/10/13 15:15:07 INFO mapreduce.Job:  map 0% reduce 0%
15/10/13 15:15:13 INFO mapreduce.Job:  map 100% reduce 0%
15/10/13 15:15:18 INFO mapreduce.Job:  map 100% reduce 50%
15/10/13 15:15:19 INFO mapreduce.Job:  map 100% reduce 100%
15/10/13 15:15:19 INFO mapreduce.Job: Job job_1444655578016_0003 completed successfully
15/10/13 15:15:19 INFO mapreduce.Job: Counters: 49
    File System Counters
        FILE: Number of bytes read=667
        FILE: Number of bytes written=347181
        FILE: Number of read operations=0
        FILE: Number of large read operations=0
        FILE: Number of write operations=0
        HDFS: Number of bytes read=524
        HDFS: Number of bytes written=1071
        HDFS: Number of read operations=9
        HDFS: Number of large read operations=0
        HDFS: Number of write operations=4
    Job Counters 
        Launched map tasks=1
        Launched reduce tasks=2
        Data-local map tasks=1
        Total time spent by all maps in occupied slots (ms)=3229
        Total time spent by all reduces in occupied slots (ms)=5230
        Total time spent by all map tasks (ms)=3229
        Total time spent by all reduce tasks (ms)=5230
        Total vcore-seconds taken by all map tasks=3229
        Total vcore-seconds taken by all reduce tasks=5230
        Total megabyte-seconds taken by all map tasks=3306496
        Total megabyte-seconds taken by all reduce tasks=5355520
    Map-Reduce Framework
        Map input records=41
        Map output records=41
        Map output bytes=573
        Map output materialized bytes=667
        Input split bytes=116
        Combine input records=0
        Combine output records=0
        Reduce input groups=36
        Reduce shuffle bytes=667
        Reduce input records=41
        Reduce output records=41
        Spilled Records=82
        Shuffled Maps =2
        Failed Shuffles=0
        Merged Map outputs=2
        GC time elapsed (ms)=66
        CPU time spent (ms)=1950
        Physical memory (bytes) snapshot=598843392
        Virtual memory (bytes) snapshot=2589491200
        Total committed heap usage (bytes)=603979776
    Shuffle Errors
        BAD_ID=0
        CONNECTION=0
        IO_ERROR=0
        WRONG_LENGTH=0
        WRONG_MAP=0
        WRONG_REDUCE=0
    File Input Format Counters 
        Bytes Read=408
    File Output Format Counters 
        Bytes Written=1071

可能遇到的問題及解決辦法

  • 執行編譯好的 class 檔案報錯
      這中執行作業的方式,在local環境下是可以的,但是在叢集環境下(偽分散式),我們需要把作業打成 jar 包,之後才能執行 hadoop 命令,hadoop 會把你的 jar 包等資源上傳到分散式檔案系統之中(這些對客戶端而言都是透明的),作業才能夠“分散式”的執行。

  • 連線不到yarn平臺之類的錯誤
      這種錯誤一般是配置mapred-site.xml的執行框架為yarn之後,沒有start-yarn.sh,即沒有在執行環境中開啟Yarn資源管理平臺,只需要執行下控制指令碼就可以了。

  • 輸出目錄已經存在
      這個在執行任務的最開始階段就會報錯,因為,預設的MapReduce框架是不會覆蓋之前的輸出目錄的,簡單的做法是在作業中判斷這個目錄是否存在,如果存在直接刪除,如下所示:

Path outputPath = new Path(output);
outputPath.getFileSystem(conf).delete(outputPath, true);

附:
  有些時候為了方便除錯,我們會在本地執行MapReduce作業,那麼,來回的修改配置檔案肯定不是什麼好事,我們這裡採用《Hadoop權威指南》中的多配置檔案方法:
  我們在etc/hadoop/目錄下新建配置檔案 : hadoop-local.xml,填寫如下的內容 :

<?xml version="1.0"?>
<configuration>
    <property>
        <name>fs.default.name</name>
        <value>file:///</value>
    </property>
    <property>
        <name>mapreduce.framework.name</name>
        <!-- 包含三種配置 : local, classical, yarn -->
        <value>local</value>
    </property>
</configuration>

  之後,想在本地執行作業的時候就可以使用如下的shell命令:

hadoop ${class_name} -conf ${conf_name} ${input_file} ${out_file}

  鑑於本人水平有限,可能會在寫作過程中出現錯誤,感謝指正!
 

相關文章