Apache #Giraph を Quick Start してみた

f:id:teppei-studio:20040226145154j:plain

Apache Giraphは、グラフ構造データをHadoop上のMapReduceで分析するためのフレームワークです。

Hadoop2.2.0のGA版がリリースされて、俄に注目が集まっているのではないかと思います。

日本語の解説記事はこのあたりをご覧ください。

Giraph - Quick Startを一通りやってみたのですが、書いてあるままやってもうまくいかないところがあったので、備忘も兼ねて、手順を残しておきたいと思います。

事前準備

私は、VirtualBox上にUbuntuを立ち上げて、そこで試しました。Ubuntsu環境作るところは省略させていただきます。ちなみにバージョンはこちらです。

尚、このチュートリアルは、OSインストールした時に作るユーザを、hdadmin にしている前提になっています。自分の環境に会わせて適宜読み替えてください。

Hadoopインストール

この辺はまだドキュメント通りに進めます。

まずはJavaのインストール

sudo apt-get install openjdk-7-jdk

インストールしたら適宜PATHを通すなどしたあと、バージョンを確認しましょう。

$ java -version
java version "1.7.0_03"
OpenJDK Runtime Environment (IcedTea7 2.1.1pre) (7~u3-2.1.1~pre1-1ubuntu2)
OpenJDK Client VM (build 22.0-b10, mixed mode, sharing)

つづいてユーザグループとして、hadoop を作り、そこに hduser を作ります。

sudo addgroup hadoop
sudo adduser --ingroup hadoop hduser

さて、Hadoopのインストールです。

su - hdadmin
cd /usr/local
sudo wget http://archive.apache.org/dist/hadoop/core/hadoop-0.20.203.0/hadoop-0.20.203.0rc1.tar.gz
sudo tar xzf hadoop-0.20.203.0rc1.tar.gz
sudo mv hadoop-0.20.203.0 hadoop
sudo chown -R hduser:hadoop hadoop

インストール後、hduser に su し、$HOME/.bashrc に以下の PATH を追加してください。

export HADOOP_HOME=/usr/local/hadoop
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64

次に、 $HADOOP_HOME/conf/hadoop-env.sh に以下のPATHを追加します。

export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
export HADOOP_OPTS=-Djava.net.preferIPv4Stack=true

続いて、hdadmin に戻ってテンポラリーファイルを用意してください。

su – hdadmin
sudo mkdir -p /app/hadoop/tmp
sudo chown hduser:hadoop /app/hadoop/tmp
sudo chmod 750 /app/hadoop/tmp

/etc/hosts を確認して、以下の設定が入っていることを確認してください。
入っていなければ、追加します。
尚、hdnode01 に設定するIPアドレスは環境に合わせて変えてください。

172.0.0.1       localhost
192.168.56.10   hdnode01

もちろんシングルノード構成なので、localhostだけでも大丈夫なのですが、きちんとhostnameを指定した方が練習になるでしょう。

Hadoopの設定ファイルを各種いじります。$HADOOP_HOME/conf配下の、core-site.xmlmapred-site.xml、そしてhdfs-site.xmlが対象です。デフォルトのファイルに、

<configuration>...</configuration>

タグを挿入して、その中に、下記それぞれの定義を挿入してください。

core-site.xml

<property>
<name>hadoop.tmp.dir</name>
<value>/app/hadoop/tmp</value>
</property>

<property> 
<name>fs.default.name</name> 
<value>hdfs://hdnode01:54310</value> 
</property>

mapred-site.xml

<property>
<name>mapred.job.tracker</name> 
<value>hdnode01:54311</value>
</property>

<property>
<name>mapred.tasktracker.map.tasks.maximum</name>
<value>4</value>
</property>

<property>
<name>mapred.map.tasks</name>
<value>4</value>
</property>

デフォルトではHadoopは一度に2つのMapを稼働させます。しかしGiraphでは4つのMapが稼働することを推奨しています。よって、シングルノードでは、上記の設定でそれを反映させて上げる必要があります。さもないとGiraphのユニットテストでこけます。

hdfs-site.xml

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

ここでレプリケーション数を1にしていますが、これはシングルノードだからです。これをデフォルトのままにしていると、レプリケーション数は3になるのでランタイムエクセプションが発生します。

次にSSHの設定です

su – hduser
ssh-keygen -t rsa -P ""
cat $HOME/.ssh/id_rsa.pub >> $HOME/.ssh/authorized_keys

一度、パスワード無しでSSHできることを確認したあと、$HADOOP_HOME/conf/mastersに以下の1行を追加してください。

hdnode01

同様に、$HADOOP_HOME/conf/slavesにも以下の設定を追加します。

hdnode01

HDFSの初期化のために、以下コマンドを実行してください。

$HADOOP_HOME/bin/hadoop namenode -format

そして、Hadoopを起動します。

$HADOOP_HOME/bin/start-all.sh

以下のコマンドを実行することで、起動状態を確認します。

jps

以下のように出力されたらOKです。(プロセスIDは環境によって変わります。)

9079 NameNode
9560 JobTracker
9263 DataNode
9453 SecondaryNameNode
16316 Jps
9745 TaskTracker

Map/Reduceジョブの実行

試しにWordCountを稼働させてみましょう。

cd /tmp/
wget http://www.gutenberg.org/cache/epub/132/pg132.txt
$HADOOP_HOME/bin/hadoop dfs -copyFromLocal /tmp/pg132.txt /user/hduser/input/pg132.txt
$HADOOP_HOME/bin/hadoop dfs -ls /user/hduser/input
$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-examples-0.20.203.0.jar wordcount /user/hduser/input/pg132.txt /user/hduser/output/wordcount

実行結果を確認してみてください。

$HADOOP_HOME/bin/hadoop dfs -cat /user/hduser/output/wordcount/p* | less

Giraphのデプロイ

さて、いよいよGiraphのデプロイですが、その前にgitmavenをインストールしておきましょう。

su - hdadmin
sudo apt-get install git
sudo apt-get install maven
mvn -version

そして、Giraphをクローンします。

cd /usr/local/
sudo git clone https://github.com/apache/giraph.git
sudo chown -R hduser:hadoop giraph
su - hduser

$HOME/.bashrcに下記のPATHをきっておきましょう

export GIRAPH_HOME=/usr/local/giraph

ビルドの前に、RC3にリセットしておきましょう。ここはドキュメントと相違しているところです。SnapshotではAPIが変わりすぎていて、この先のサンプルがドキュメント通り動きません。それだけ変化が大きいプロダクトということですね。

git reset --hard release-1.0.0-RC3


そしてビルドです。

source $HOME/.bashrc
cd $GIRAPH_HOME
mvn package -DskipTests

Giraph Job の稼働

さてGiraphを稼働させてみましょう。ここではSimpleShortestPathsComputationというサンプルを稼働させます。ある地点(今回はID=1の地点)からそれぞれの地点への最短距離を計算する処理です。この処理のインプットではJsonLongDoubleFloatDoubleVertexInputFormatというフォーマットが要求されます。このフォーマットで/tmp/tiny_graph1.txtファイルを作成しましょう。中身は以下のようになります。

[0,0,[[1,1],[3,3]]]
[1,0,[[0,1],[2,2],[3,1]]]
[2,0,[[1,2],[4,4]]]
[3,0,[[0,3],[1,1],[4,4]]]
[4,0,[[3,4],[2,4]]]

これを図示してみましょう。

f:id:teppei-studio:20131111165011p:plain

赤線と赤数字は、1番地点からの各地点への最短距離を示したものです。

では、このファイルをHDFSに配置し、

$HADOOP_HOME/bin/hadoop dfs -copyFromLocal /tmp/tiny_graph1.txt /user/hduser/input/tiny_graph1.txt
$HADOOP_HOME/bin/hadoop dfs -ls /user/hduser/input

いざJOBを稼働させてみましょう。
このコマンドのオプションの指定の仕方もドキュメントとは微妙に変えていますのでご注意ください。

$HADOOP_HOME/bin/hadoop jar \
	$GIRAPH_HOME/giraph-examples/target/giraph-examples-1.0.0-for-hadoop-0.20.203.0-jar-with-dependencies.jar \
	org.apache.giraph.GiraphRunner org.apache.giraph.examples.SimpleShortestPathsVertex \
	-vif org.apache.giraph.io.formats.JsonLongDoubleFloatDoubleVertexInputFormat \
	-vip /user/hduser/input/tiny_graph1.txt \
	-of org.apache.giraph.io.formats.IdWithValueTextOutputFormat \
	-op /user/hduser/output/shortestpaths1 \
	-w 1

処理が完了したら出力結果を確認してみましょう。

$HADOOP_HOME/bin/hadoop dfs -cat /user/hduser/output/shortestpaths1/p* | less

このような出力結果が得られたはずです。

0	1.0
2	2.0
1	0.0
3	1.0
4	5.0

左の列が1番地点から何番地点なのかを示していて、右の列が距離を示しています。上の図の通りになっていることが分かると思います。

さて、ここで、インプットのファイルを少しいじって、出力もちゃんと変化するか見てみましょう。

[0,0,[[1,1],[3,3]]]
[1,0,[[0,1],[2,2],[3,3]]]
[2,0,[[1,2],[4,4]]]
[3,0,[[0,3],[1,3],[4,4]]]
[4,0,[[3,4],[2,4]]]

1番から3番までの距離が1だったのが3に、逆に3番から1番への距離が1だったのが3にしてみました。

図示するとこのような感じです。

f:id:teppei-studio:20131111170951p:plain

同じJOBを実行すると、以下のようになりました。

0	1.0
2	2.0
1	0.0
3	3.0
4	6.0

3番までの距離が3に、4番までの距離が6になりました。
正しく計算できているようですね。

その他のサンプル

Giraphはサンプルが数多く用意されています。

が、他のサンプルについては、どんなインプットフォーマット、アウトプットフォーマットを指定したらいいのか全然分からん...!この辺は誰かチャレンジしてブログアップしてくれないかなぁと期待しています。