前回(http://d.hatena.ne.jp/lopnor/20080831/1220183688)サンプルプログラムを動かすところまで行きましたけど、今回は例のid:naoyaのhadoop streamingでアクセス解析(http://d.hatena.ne.jp/naoya/20080513/1210684438)するのをやってみます。というかなんとかたどり着いたのでまとめを書きます。 *ec2の使い方 id:rx7さんがとても丁寧に説明されている資料(http://d.hatena.ne.jp/rx7/20080528/p1)があるので、そちらを読めば完璧だと思います。僕もこれでec2が使えるようになりました。 *hadoop-ec2の使い方 https://codezine.jp/article/detail/2841がイントロダクション。http://d.hatena.ne.jp/lopnor/20080831/1220183688は超適当なまとめ。あんまり参考にならないかも。http://wiki.apache.org/hadoop/AmazonEC2が本家まとめ。ここまででサンプルプログラムの円周率の計算ができるようになるはず。

  • hadoop streamingの説明 http://d.hatena.ne.jp/naoya/20080513/1210684438とhttp://d.hatena.ne.jp/naoya/20080531/1212245982の先にあるpptをぜひ。実はpptまでいって初めていろいろわかったことがあったので、ぜひ。
  • ということで、hadoop streaming on ec2 まず、適当にアクセスログを用意します。
[danjou@luisa] $ mkdir ~/tmp/20080911
[danjou@luisa] $ cd ~/tmp/20080911
[danjou@luisa] $ cp /var/log/httpd/access_log .

つぎに、例のperlスクリプトmapper.pl、reducer.plを書きます。

#!/usr/local/bin/perl


# mapper.pl

# originally by id:naoya


use strict;
use warnings;

while (<>) {
    chomp;
    my @segments = split /\s+/;
    printf "%s\t%s\n", $segments[8], 1;
}
#!/usr/bin/perl


# reducer.pl

# originally by id:naoya


use strict;
use warnings;

my %count;
while (<>) {
    chomp;
    my ($key, $value) = split /\t/;
    $count{$key}++;
}

while (my ($key, $value) = each %count) {
    printf "%s\t%s\n", $key, $value;
}

ローカルで実行してみましょう

[danjou@luisa] $ cat access_log | perl mapper.pl | perl reducer.pl
200	2740
302	117
404	2

という感じでステータスコードが数えられました。ではこれと同じことをhadoopでやってみましょう。作業ディレクトリは現状こんな感じ。

[danjou@luisa] $ ls
access_log mapper.pl  reducer.pl

hadoop-ec2でクラスタを起動する前に、hadoop-ec2-env.shをいじっておきます。下記部分のCOMPRESS=trueのところを、COMPRESS=falseにしておいてください。trueのままでやると、結果ファイルが圧縮されてしまって、元に戻す方法をまだ僕は知らないのです><

# Boot parameters

MAX_MAP_TASKS=2
MAX_REDUCE_TASKS=2
#COMPRESS=true

COMPRESS=false

で、以下のようにして”hadoop-test”という名前のクラスタをワーカー2台で起動。

[danjou@luisa] $ hadoop-ec2 launch-cluster hadoop-test 2

処理に必要なファイルをファイルをマスタマシンに転送します。

[danjou@luisa] $ hadoop-ec2 push hadoop-test access_log
[danjou@luisa] $ hadoop-ec2 push hadoop-test mapper.pl
[danjou@luisa] $ hadoop-ec2 push hadoop-test reducer.pl

1ファイルずつかいっ!という感じですが。いよいよマスタにログイン。

[danjou@luisa] $ hadoop-ec2 login hadoop-test
Logging in to host ec2-00-00-00-00.compute-1.amazonaws.com.

         __|  __|_  )  Fedora 8
         _|  (     /    32-bit
        ___|\___|___|

 Welcome to an EC2 Public Image
                       :-)
    Base

 --[ see /etc/ec2/release-notes ]--

[root@domU-00-00-00-00-00-00 ~]# 

ログインしました。lsしてみると、さっき転送したファイルがありますね。

[root@domU-00-00-00-00-00-00 ~]# ls
access_log  ec2-ami-tools-1.3-19974.noarch.rpm  hadoop-init  mapper.pl  reducer.pl

今度は、access_logを分散ファイルシステムに突っ込みます。

[root@domU-00-00-00-00-00-00 ~]# hadoop fs -put access_log access_log
08/09/10 21:46:48 WARN fs.FileSystem: "domU-12-31-38-00-90-C6.compute-1.internal:50001" is a deprecated filesystem name. Use "hdfs://domU-00-00-00-00-00-00.compute-1.internal:50001/" instead.
08/09/10 21:46:49 WARN fs.FileSystem: "domU-00-00-00-00-00-00.compute-1.internal:50001" is a deprecated filesystem name. Use "hdfs://domU-00-00-00-00-00-00.compute-1.internal:50001/" instead.
08/09/10 21:46:49 WARN fs.FileSystem: "domU-00-00-00-00-00-00.compute-1.internal:50001" is a deprecated filesystem name. Use "hdfs://domU-00-00-00-00-00-00.compute-1.internal:50001/" instead.
08/09/10 21:46:49 WARN fs.FileSystem: "domU-00-00-00-00-00-00.compute-1.internal:50001" is a deprecated filesystem name. Use "hdfs://domU-00-00-00-00-00-00.compute-1.internal:50001/" instead.

なんかワーニングが出るんですけど、気にしない!

[root@domU-00-00-00-00-00-00 ~]#  hadoop fs -ls 2>/dev/null
Found 1 items
/user/root/access_log	<r 3>	506916	2008-09-10 21:46	rw-r--r--	root	supergroup

こんな感じで、分散ファイルシステム側にファイルが置けました。では、いざ処理を実行してみましょう。

[root@domU-00-00-00-00-00-00 ~]#  hadoop jar \

> /usr/local/hadoop-0.17.0/contrib/streaming/hadoop-0.17.0-streaming.jar \

> -input access_log \

> -output output \

> -mapper 'perl mapper.pl' \

> -reducer 'perl reducer.pl' \

> -file mapper.pl \

> -file reducer.pl 

ここで、-fileというオプションが二つ渡されていますが、この指定をしておくと、実行するperlスクリプトが処理時に各ワーカーに転送されます。ですので、各ワーカーにいちいちインストールしなくてもいいので、今回みたいなec2のデフォルトのイメージでポイッと処理することができます。 で、結果を見てみると、

[root@domU-00-00-00-00-00-00 ~]#  hadoop fs -ls output 2>/dev/null
Found 2 items
/user/root/output/_logs	<dir>		2008-09-10 22:31	rwxr-xr-x	root	supergroup
/user/root/output/part-00000	<r 3>	23	2008-09-10 22:31	rw-r--r--	root	supergroup
[root@domU-00-00-00-00-00-00 ~]#  hadoop fs -cat output/part-00000 2>/dev/null
200	2740
302	117
404	2

つうことで、できたーーーーー!!コマンドラインで一瞬だったのにこっちはえらい時間がかかりましたな。ということで、やっぱり大量のデータでないとうまみはないですね。でも大量のデータだとものごっついおいしいです。これでやっと入門編が終わったので、これから実用的な使い方を考えていこうと思います。 あ、最後に

[root@domU-00-00-00-00-00-00 ~]# exit
logout

Connection to ec2-00-00-00-00.compute-1.amazonaws.com closed.
[danjou@luisa] $ hadoop-ec2 terminate-cluster hadoop-test

としてクラスタを終了させておしまいです。