這裡示範如何在 Ubuntu Linux 的環境中,架設單節點 Hadoop 分散式運算的大資料分析測試環境。

Apache Hadoop 是一個分散式計算的架構,可用於巨量資料(big data)的處理與分析,其原理是利用多台電腦組合成為大型的 Hadoop 叢集電腦,以特殊的 HDFS 檔案系統讓大量的資料分散儲存於各個節點中,而在計算與分析資料時,則是使用 MapReduce 等演算法將計算工作分散在各個節點中平行處理,可用於 PB 級以上的資料儲存與分析。


由於 Hadoop 分散式計算的架構比一般程式更複雜,所以通常在程式的開發與測試階段都會使用單節點的 Hadoop 環境,不管是設備架設與程式除錯都比較方便,以下是使用 Ubuntu Linux 系統架設 Hadoop 單節點測試環境的步驟。

Java 開發與執行環境

安裝 Java 的開發與執行環境,安裝流程請參考 Ubuntu Linux 安裝 Oracle 或 OpenJDK 的 Java JRE 與 JDK 步驟教學

安裝好之後,確認一下 java 是否正常。

java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

安裝 Hadoop

安裝 Hadoop 前要決定執行 Hadoop 用的帳號,如果是開發程式用的 Hadoop 測試環境,就使用一般的 Linux 使用者帳號即可。

Hadoop 的官方網站下載 Hadoop:

wget ftp://ftp.twaren.net/Unix/Web/apache/hadoop/common/hadoop-2.7.3/hadoop-2.7.3.tar.gz

解壓縮後,將 Hadoop 的目錄放置在要安裝的位置:

tar zxvf hadoop-2.7.3.tar.gz
sudo mv hadoop-2.7.3 /opt/

設定 Hadoop 用的 Java

Hadoop 執行時會讀取 JAVA_HOME 環境變數來取得 Java 的執行環境,請先檢查一下自己的 JAVA_HOME 是否有設定好:

echo $JAVA_HOME
/usr/lib/jvm/java-8-oracle

若沒有設定好,可以在自己的 ~/.bash_profile~/.bashrc 中加入類似這樣的設定:

export JAVA_HOME="/usr/lib/jvm/java-8-oracle"

讓自己的帳號登入系統時就自動設定好 JAVA_HOME 環境變數。

另外一種設定方式是編輯 Hadoop 目錄下 etc/hadoop/hadoop-env.sh 這個 Hadoop 設定檔,找到其中的 JAVA_HOME 設定:

# The java implementation to use.
export JAVA_HOME=${JAVA_HOME}

JAVA_HOME 替換為自己的 Java 安裝路徑即可。

設定 PATH 環境變數

將 Hadoop 的執行檔加入自己的 PATH 環境變數中,這樣在執行 Hadoop 時會比較方便。在 ~/.bashrc 中加入:

export HADOOP_HOME=/opt/hadoop-2.7.3
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

直接載入 ~/.bashrc 的設定並測試執行 hadoop 指令:

source ~/.bashrc
hadoop version
Hadoop 2.7.3
Subversion https://git-wip-us.apache.org/repos/asf/hadoop.git -r baa91f7c6bc9cb92be5982de4719c1c8af91ccff
Compiled by root on 2016-08-18T01:41Z
Compiled with protoc 2.5.0
From source with checksum 2e4ce5f957ea4db193bce3734ff29ff4
This command was run using /opt/hadoop-2.7.3/share/hadoop/common/hadoop-common-2.7.3.jar

Hadoop 單機模式測試

Hadoop 有幾種執行模式,分別適用於不同的情況:

單機模式(tandalone mode)
所有的 Hadoop 程式都在單一的 JVM 中執行,沒有啟動 Hadoop daemons,這樣測試與除錯都會比較容易(尤其是 MapReduce 類型的程式),很適合用於程式開發階段。
模擬分散模式(pseudo-distributed mode)
使用單一台機器,多個 Java 行程來執行 Hadoop 程式,模擬分散式架構。
完整分散模式(fully-distributed mode)
使用多台機器平行執行 Hadoop 程式,用於正式的 Hadoop 叢集電腦。

Hadoop 在安裝好的時候,預設的設定就是單機模式,所以如果您需要的 Hadoop 環境就是單機模式,那就不需要再去更動它的設定檔了。

我們可以使用 Hadoop 內建的範例測試一下 Hadoop 是否可以正常執行,首先複製一些 Hadoop 的 XML 設定檔作為測試用的文字資料:

cp -r $HADOOP_HOME/etc/hadoop input

執行內建的 MapReduce 範例程式,這個範例會將 input 中的檔案以 MapReduce 的方式,用正規表達式(regular expression)搜尋,並將結果儲存於 output 目錄中:

hadoop jar 
  $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar 
  grep input output 'dfs[a-z.]+'

在執行這個 Hadoop 範例程式時,會有相當多的訊息,執行完畢之後,會產生一個 output 目錄:

ls output/
part-r-00000  _SUCCESS

若程式執行成功的話,在 output 目錄中會建立一個 _SUCCESS 檔案,而 part-r-00000 就是執行結果:

cat output/part-r-00000
6	dfs.audit.logger
4	dfs.class
3	dfs.server.namenode.
2	dfs.period
2	dfs.audit.log.maxfilesize
2	dfs.audit.log.maxbackupindex
1	dfsmetrics.log
1	dfsadmin
1	dfs.servers
1	dfs.replication
1	dfs.file

設定 Hadoop 模擬分散模式

Hadoop 的模擬分散執行模式可以讓單一台機器執行多個 Java 行程,模擬叢集電腦的執行狀況,以下是將 Hadoop 設定為模擬分散模式的設定方式。

Hadoop 主要的設定都是寫在 etc/hadoop 目錄中的 XML 檔裡面,以下是比較重要的 XML 設定檔:

  • core-site.xml:Hadoop 基本設定檔。
  • hdfs-site.xml:HDFS 設定檔。
  • mapred-site.xml:MapReduce 設定檔。
  • yarn-site.xml:YARN 設定檔。

更改 core-site.xml 設定檔內容:

<configuration>
  <property>
    <name>fs.defaultFS</name>
    <value>hdfs://localhost:9000</value>
  </property>
</configuration>

更改 hdfs-site.xml 設定檔內容:

<configuration>
  <property>
    <name>dfs.replication</name>
    <value>1</value>
  </property>
</configuration>

設定 SSH 金鑰認證登入

安裝 ssh 伺服器:

sudo apt-get install openssh-server

設定 ssh 金鑰認證登入:

ssh-keygen
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 0600 ~/.ssh/authorized_keys

檢查 ssh 登入是否需要密碼:

ssh localhost

將資料放入 HDFS

HDFS 檔案系統在第一次使用前,要先進行格式化的動作:

hdfs namenode -format

啟動 NameNode 與 DataNode daemon:

start-dfs.sh

打開 NameNode 的網頁介面網址 http://localhost:50070/,看看網頁是否可以正常顯示:

NameNode 網頁介面

建立使用者用的目錄:

hdfs dfs -mkdir -p /user/gtwang

將資料放進 HDFS 中:

hdfs dfs -put $HADOOP_HOME/etc/hadoop input

查看一下資料:

hdfs dfs -ls input

執行 MapReduce 測試程式

執行 MapReduce 程式:

hadoop jar 
  $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar 
  grep input output 'dfs[a-z.]+'

將資料取回並查看結果:

hdfs dfs -get output output
cat output/*
6	dfs.audit.logger
4	dfs.class
3	dfs.server.namenode.
2	dfs.period
2	dfs.audit.log.maxfilesize
2	dfs.audit.log.maxbackupindex
1	dfsmetrics.log
1	dfsadmin
1	dfs.servers
1	dfs.file

若不想取回資料,也可以直接使用以下的指令查看結果:

hdfs dfs -cat output/*

執行完畢之後,關閉 daemons:

stop-dfs.sh

補充資料

如果在執行時出現類似這樣的錯誤訊息:

17/02/21 10:32:48 WARN hdfs.DFSClient: Caught exception 
java.lang.InterruptedException
	at java.lang.Object.wait(Native Method)
	at java.lang.Thread.join(Thread.java:1249)
	at java.lang.Thread.join(Thread.java:1323)
	at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.closeResponder(DFSOutputStream.java:609)
	at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.closeInternal(DFSOutputStream.java:577)
	at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:573)

這個看起來是 Hadoop 的 bug,暫時可以忽略它。

參考資料:Apache Hadoop台大計資中心DigitalOceanBogoToBogoiThome