Hadoop入門者向けの注意点とかコツ(2)

前回クラスタの構成について述べました。今回はプログラミングを行う上での注意点について書いていきます。

プログラミング環境

Eclipseでプログラミングする場合について述べます。

  • Eclipse Pluginは動かない
    • /opt/hadoop/contrib/eclipse-plugin/にEclipseプラグインが入ってるんですが、このプラグインを使ったプログラムの実行、HDFSの操作はエラーが出てできませんでした。ただMapReduceプロジェクトを作成するとき必要なライブラリパスを追加してくれるのは楽です。
  • 擬似分散モードでプログラムを動かす場合、通常の実行(Java Application)でもok.
  • 完全分散モードでプログラムを動かす場合、通常の実行(Java Application)でもokなときもある.
  • 完全分散モードで正しく動かすにはjarファイルにまとめてから実行する必要がある
    • これを簡単に行うにはantの設定が必要

antの設定は以下の通り

<?xml version="1.0" encoding="UTF-8"?>
<project name="project" default="develop" basedir="./">
	<description>Hadoop開発用</description>

	<property name="src-dir" value="./src" />
	<property name="bin-dir" value="./bin" />
	<property name="jar-dir" value="./jar" />
	<property name="jar-file" value="${jar-dir}/sample.jar" />

	<property name="hadoop-bin-dir" value="/opt/hadoop/bin" />
	<property name="hadoop-dir" value="/opt/hadoop/" />

	<property name="target-class" value="rulebase.hadoop.main.Main" />

	<target name="develop" depends="remove-jar,jar,run">
	</target>

	<target name="jar">
		<echo>make jar</echo>

		<jar jarfile="${jar-file}">
			<fileset dir="${bin-dir}" includes="**/*.class" />
			<fileset dir="${hadoop-dir}" includes="**/*.jar" />
		</jar>
	</target>

	<target name="remove-jar">
		<echo>remove jar</echo>
		<delete file="${jar-file}">
		</delete>
	</target>

	<target name="run">
		<exec executable="/opt/hadoop/bin/hadoop">
			<arg value="jar" />
			<arg value="${jar-file}" />
			<arg value="${target-class}" />
		</exec>
	</target>
</project>

テスト方法

この順番でテストします。HDFSはファイルの準備にとても時間がかかるので最初はローカルファイルを利用してテストしましょう。

  1. ローカルファイルを利用して擬似分散モードで実行
  2. HDFSを利用して擬似分散モードで実行
  3. HDFSを利用して完全分散モードで実行

なお完全分散モードの場合、タスクトラッカーでSystem.out.printlnを記述していてもメッセージは表示されません。メッセージを出力したいのであれば、HDFS上のファイルを利用するのがいいと思います。

プログラミングの注意点

  • Configureオブジェクトの扱い方はこのフレームワークの肝なのでよく勉強しておきましょう
    • デフォルト設定が存在する
    • Toolを使うとxmlファイルから設定を読み込める
    • 後からプロパティを設定できる
  • MapReduceのライブラリは新しいAPIと古いAPIの2種類あります。古い方はorg.apache.hadoop.mapred、新しい方はorg.apache.hadoop.mapreduceに入ってます。古いAPIはとても使いにくいので新しいAPIをおすすめします。
  • プログラム中で絶対パスやホストの決め打ちを利用しないようにしましょう。例えばhdfs://localhost:9000/user/hadoopやfile://home/hadoopです。環境が変わっても実行できるようにしておいてください。
  • key、valueにはWritableインタフェイスを実装したものしか使えません。よくkey,valueには任意のデータが使えるとありますが誤解を招く表現ですね。
  • map関数を実装しているクラス、reduce関数を実装しているクラス、それらを呼び出すクラスは別のVM上で動きます。そのためオブジェクトを共有することができません。
    • 簡単な文字列ならConfigurationオブジェクトを通じてmapのクラスやreduceのクラスに渡すことができます
    • オブジェクトを渡したい場合はシリアライゼーションして渡す必要があります
  • reduce関数のIteratorで取得できるオブジェクトは全て同じものです。next()を呼び出すたびにオブジェクトの値が変わるだけです。別の値で保存したい場合、オブジェクトをcloneしてください。
  • reduce関数のIteratorは1回しか回すことができません。2回以上回したければリストなどに保存しておいてください。

プログラムの実行時

java.lang.IllegalArgumentException: Wrong FS:
hdfs://host:9000/user/hadoop/file  Expected file:////

上のようなエラーがよく出ると思います。これはローカルファイルを期待していたのに、指定されたのがHDFSのファイルだという意味です。Configureのfs.default.nameで指定したファイルシステムを使う必要があります。


以上です