S-JIS[2014-03-29/2014-04-01] 変更履歴

Asakusa Framework WindGate SSH

Asakusa FrameworkWindGate SSHのメモ。


概要

WindGateはRDB(やローカルファイル)と連携するコンポーネント。

よくある構成ではAsakusaアプリケーション(WindGateを含む)をHadoopクラスター(たいていはマスターノード)に配置し、そこからYAESSを使って起動する。

よくある構成の例
DBサーバー   Hadoopクラスター
RDB ←(JDBC)→ Asakusaアプリ
(WindGate)
←→ HDFS
   
YAESS
   

しかしRDBとHadoopクラスターとの直接接続(通信)が出来ない(許可されない)環境も有り得る。
そうした場合、RDBと通信を行う機能(つまりWindGate)を別サーバーに出すという構成にすることが出来る。

この構成では、RDBとWindGate間はJDBC、WindGateとHadoopクラスター間はSSHを使ってデータ転送される。

WindGateを別サーバーに配置した構成の例
DBサーバー   WindGateサーバー   Hadoopクラスター
RDB ←(JDBC)→ WindGate
(Asakusaアプリ)
←(SSH)→ HDFS
   
YAESS
→(SSH)→ Asakusaアプリ

この構成の場合、Asakusaアプリ(ASAKUSA_HOME配下一式)をWindGateサーバーとHadoopクラスター(マスターノード)の両方に配置しておく必要がある。
そして、WindGateのプロファイルにRDBへ接続する為のJDBCの設定と、HadoopクラスターにSSH接続する為の設定をする。
また、YAESSもHadoopクラスター(マスターノード)にSSHで入ってhadoopコマンドを実行するので、SSH接続の設定が必要となる。


例として、WindGateサーバー上のローカルファイル(CSVファイル)を読み込んでHDFS上にCSVファイルとして書き込むアプリケーション・構成を作ってみる。
(RDBを用意するのは面倒なので、ローカルファイル読み込みとする。RDBの場合は、DMDLに付ける属性Importer記述およびWindGateプロファイルの内容が異なるだけ)

Asakusaアプリケーションの起動(YAESSのシェルの実行)はWindGateサーバー上で行う。

WindGateサーバー   Hadoopクラスター
ローカルファイル WindGate
(Asakusaアプリ)
→(SSH)→ HDFS
   
YAESS
→(SSH)→ Asakusaアプリ

WindGateサーバー上では「asakusa」というユーザーでAsakusaアプリケーション一式(WindGateやYAESSを含む)を扱うものとする。
Hadoopクラスター上では「hadoop」というユーザーでHadoopの操作およびAsakusaアプリケーション一式の配置を行うものとする。

各サーバーの構成
サーバー ホスト名 ディレクトリー 説明
WindGateサーバー hishidama-gateway /home/asakusa/asakusa Asakusaアプリケーション
/home/asakusa/.ssh SSH設定
/home/hadoop Hadoop
Hadoopクラスター(マスターノード) hishidama-hadoop /home/hadoop Hadoop
/home/hadoop/.ssh SSH設定
/home/hadoop/asakusa Asakusaアプリケーション

AsakusaFWのバージョンは0.6.1、Linux上でGradleプラグインを使ってAsakusaアプリケーションを開発する想定。


ホスト名の設定

今回の例では、WindGateサーバーのホスト名を「hishidama-gateway」、Hadoopクラスターのマスターノードのホスト名を「hishidama-hadoop」とする。
実験するだけであれば、Hadoopクラスターはスタンドアローンでよい(仮想分散にもする必要は無い)。

WindGateサーバーとマスターノードの/etc/hostsを設定しておく。

/etc/hosts:

192.168.1.23 hishidama-hadoop
192.168.1.24 hishidama-gateway

インストールしておくべきソフトウェア

Hadoopクラスターには当然Hadoopをインストールしておく。

WindGateサーバーにもHadoopをインストールする必要がある。
これは、シーケンスファイルを扱うライブラリー(jarファイル)を使用する為らしい。[2014-04-01]
(なお、例えばHadoopクラスター側がMapRの場合、WindGateサーバーにインストールするHadoopはMapRである必要は無く、MapRのベースとなるHadoopバージョン(1.0.3とか)と一致するApache Hadoopであれば良いらしい)

今回の例では、WindGateサーバーとHadoopクラスターの両方とも「/home/hadoop」にHadoopをインストールしてあるものとする。
すなわち、hadoopコマンドの場所(環境変数HADOOP_CMD)は/home/hadoop/bin/hadoopとなる。


SSHの設定

WindGateサーバーからHadoopクラスター(マスターノード)にSSH通信できる必要がある為、SSHの設定を行う。

  1. WindGateサーバー上でSSHキーを生成する。
    1. WindGateサーバーにasakusaユーザーでログインする。
    2. 「.ssh」ディレクトリーを作成する。
      $ cd /home/asakusa
      $ mkdir .ssh
      $ chmod 700 .ssh
    3. キーを生成する。
      passphrase(SSH接続用のパスワード。UNIXユーザーのパスワードとは無関係)は、今回は「hishidama-ssh-password」とする
      $ ssh-keygen -t dsa
      Generating public/private dsa key pair.
      Enter file in which to save the key (/home/asakusa/.ssh/id_dsa): 
      Enter passphrase (empty for no passphrase): 
      Enter same passphrase again: 
      Your identification has been saved in /home/asakusa/.ssh/id_dsa.
      Your public key has been saved in /home/asakusa/.ssh/id_dsa.pub.
      〜
      $ ls
      id_dsa  id_dsa.pub
  2. HadoopクラスターのマスターノードにSSHキーを配置する。
    1. マスターノードにhadoopユーザーでログインする。
    2. 「.ssh」ディレクトリーを作成する。
      $ cd /home/hadoop
      $ mkdir .ssh
      $ chmod 700 .ssh
    3. WindGateサーバー上に作成したid_dsa.pubを.sshの下に転送してくる。
    4. id_dsa.pubをauthorized_keysに登録する。
      $ cd /home/hadoop/.ssh
      $ cat id_dsa.pub >> authorized_keys
      $ chmod 600 authorized_keys
  3. WindGateサーバーからHadoopクラスターのマスターノードにSSH接続できることを確認する。
    1. WindGateサーバーにasakusaユーザーでログインする。
    2. SSH接続してみる。
      $ ssh -i /home/asakusa/.ssh/id_dsa hadoop@hishidama-hadoop
      キー生成時に設定したパスワードを入力して、接続できればOK。

Asakusaアプリケーションの作成

今回の例では、WindGateを使ってローカルのCSVファイルを読み込み、その内容をそのままDirect I/OでHDFS上にCSVファイルを書き込む。
つまり、ImporterはWindGate、ExporterはDirect I/Oになる。
どちらもCSVファイルなので、データモデル定義(DMDL)では@windgate.csv@directio.csvを指定する。
(RDBを入力とする場合は、@windgate.csvの代わりに@windgate.jdbcを指定する)

src/main/dmdl/example.dmdl

@windgate.csv
@directio.csv
example_model = {

    text1 : TEXT;

    text2 : TEXT;
};

src/main/java/com/example/batchapp/jobflow/ExampleModelFromLocalCsv.java:

package com.example.batchapp.jobflow;

import com.example.modelgen.dmdl.csv.AbstractExampleModelCsvImporterDescription;

public class ExampleModelFromLocalCsv extends AbstractExampleModelCsvImporterDescription {

	@Override
	public String getProfileName() {
		return "gateway";
	}

	@Override
	public String getPath() {
		return "input/example.csv";
	}

	@Override
	public DataSize getDataSize() {
		return DataSize.LARGE;
	}
}

今回のImporterはWindGateなので、プロファイルを定義する必要がある。今回のプロファイル名は「gateway」としてある。
(RDBから読み込む場合は、RDB用のImporterを作る。ファイルのパスの代わりにテーブル名とかSELECT文のWHERE条件とかを書く)

src/main/java/com/example/batchapp/jobflow/ExampleModelToHdfsCsv.java:

package com.example.batchapp.jobflow;

import com.example.modelgen.dmdl.csv.AbstractExampleModelCsvOutputDescription;
import java.util.List;

public class ExampleModelToHdfsCsv extends AbstractExampleModelCsvOutputDescription {

	@Override
	public String getBasePath() {
		return "hadoop";
	}

	@Override
	public String getResourcePattern() {
		return "output/example*.csv";
	}
}

今回のExporterはDirect I/Oなので、ベースパスを定義する必要がある。今回のベースパスは「hadoop」としてある。
(これが具体的にどのディレクトリーを指すのかは、core/conf/asakusa-resources.xmlのcom.asakusafw.directio.〜.fs.pathで定義する)

src/main/java/com/example/batchapp/jobflow/ExampleJob.java:

package com.example.batchapp.jobflow;

import com.asakusafw.vocabulary.flow.Export;
import com.asakusafw.vocabulary.flow.FlowDescription;
import com.asakusafw.vocabulary.flow.Import;
import com.asakusafw.vocabulary.flow.In;
import com.asakusafw.vocabulary.flow.JobFlow;
import com.asakusafw.vocabulary.flow.Out;
import com.example.modelgen.dmdl.model.ExampleModel;

@JobFlow(name = "ExampleJob")
public class ExampleJob extends FlowDescription {

	private In<ExampleModel> in;
	private Out<ExampleModel> out;

	public ExampleJob(
		@Import(name = "in", description = ExampleModelFromLocalCsv.class) In<ExampleModel> in,
		@Export(name = "out", description = ExampleModelToHdfsCsv.class) Out<ExampleModel> out
	) {
		this.in = in;
		this.out = out;
	}

	@Override
	protected void describe() {
		this.out.add(this.in); //入力データをそのまま出力するだけ
	}
}

src/main/java/com/example/batchapp/jobflow/ExampleBatch.java:

package com.example.batchapp.batch;

import com.asakusafw.vocabulary.batch.Batch;
import com.asakusafw.vocabulary.batch.BatchDescription;
import com.example.batchapp.jobflow.ExampleJob;

@Batch(name = "ExampleBatch")
public class ExampleBatch extends BatchDescription {

	@Override
	protected void describe() {
		run(ExampleJob.class).soon();
	}
}

WindGateのプロファイルの設定

Importer用のWindGateのプロファイルを定義する。
WindGateサーバーに配置するファイルの置き場として、src/dist/gatewayというディレクトリーを作成し、その下にファイルを置いておく。
WindGateサーバーに配置する為のAsakusaアーカイブを作る際にsrc/dist/gatewayの下のファイルを含めるようにする)

デフォルトのASAKUSA_HOME/windgate/profile/asakusa.propertiesをコピーして、必要な部分を記述する。

プロファイルのファイル名は何でもよいが、ImporterのgetProfileName()と合わせる。
(ファイル名がzzz.propertiesなら、getProfileName()は「return "zzz";」とする)

src/dist/gateway/windgate/profile/gateway.properties

## Core
core.maxProcesses=4

## Resources

# Local File System
resource.local=com.asakusafw.windgate.stream.file.FileResourceProvider
resource.local.basePath=/tmp/windgate

# JDBC
#resource.jdbc=com.asakusafw.windgate.jdbc.JdbcResourceProvider
#resource.jdbc.driver=org.postgresql.Driver
#resource.jdbc.url=jdbc:postgresql://localhost:5432/asakusa
#resource.jdbc.user=asakusa
#resource.jdbc.password=asakusa
#resource.jdbc.batchGetUnit=1000
#resource.jdbc.batchPutUnit=1000
#resource.jdbc.connect.retryCount=3
#resource.jdbc.connect.retryInterval=10
#resource.jdbc.statement.truncate=TRUNCATE TABLE {0}
#resource.jdbc.properties.loginTimeout=10

# Hadoop File System
#resource.hadoop=com.asakusafw.windgate.hadoopfs.HadoopFsProvider
#resource.hadoop.compression=org.apache.hadoop.io.compress.DefaultCodec
#resource.hadoop.basePath=hdfs://localhost/user/${USER}

# Hadoop File System (for Remote Hadoop Cluster via SSH)
resource.hadoop=com.asakusafw.windgate.hadoopfs.jsch.JschHadoopFsProvider
resource.hadoop.user=hadoop
resource.hadoop.host=hishidama-hadoop
resource.hadoop.port=22
resource.hadoop.privateKey=${HOME}/.ssh/id_dsa
resource.hadoop.passPhrase=hishidama-ssh-password
resource.hadoop.compression=org.apache.hadoop.io.compress.DefaultCodec
resource.hadoop.env.HADOOP_CMD=/home/hadoop/bin/hadoop
resource.hadoop.env.ASAKUSA_HOME=/home/hadoop/asakusa

## Session
session=com.asakusafw.windgate.file.session.FileSessionProvider
session.directory=${ASAKUSA_HOME}/windgate/var/session/${WINDGATE_PROFILE}

## Process
process.basic=com.asakusafw.windgate.core.process.BasicProcessProvider

resource.local.basePathでローカルファイルシステムのパス(ディレクトリー)を指定する。
(RDBを対象にする場合は、resource.jdbc系のプロパティーを記述する)

resource.hadoopにはJschHadoopFsProviderの方を有効にする。
(デフォルトのプロファイルのasakusa.propertiesではHadoopFsProviderが有効になっているので、こちらはコメントアウトする)
resource.hadoopのuser・host・port・privateKey・passPhraseは、SSHで接続する情報。
resource.hadoopのenv.HADOOP_CMDやenv.ASAKUSA_HOMEは、接続先(つまりHadoopクラスターのマスターノード)内での場所を指定する。


YAESSの設定

今回の例では、WindGateサーバー上からYAESSを起動し、別の場所にあるHadoopクラスターを使用する。

YAESSには別サーバー(Hadoopクラスター)上にあるAsakusaアプリケーションを起動できる機能があるが、
その為に、HadoopクラスターにSSH接続できるようにWindGateサーバー上のYAESSも設定する必要がある。

デフォルトのASAKUSA_HOME/yaess/conf/yaess.propertiesをコピーして、必要な部分を記述する。

src/dist/gateway/yaess/conf/yaess.properties

core = com.asakusafw.yaess.basic.BasicCoreProfile
core.version = 0.1

## file lock
lock = com.asakusafw.yaess.basic.BasicLockProvider
lock.scope = world
lock.directory = ${ASAKUSA_HOME}/yaess/var/lock

## logging monitor
monitor = com.asakusafw.yaess.basic.BasicMonitorProvider
monitor.stepUnit = 0.05

## single threaded job scheduler
scheduler = com.asakusafw.yaess.basic.BasicJobScheduler

## local direct execution
#hadoop = com.asakusafw.yaess.basic.BasicHadoopScriptHandler
#hadoop.resource = hadoop-master
#hadoop.env.HADOOP_CMD = /usr/bin/hadoop
#hadoop.env.ASAKUSA_HOME = ${ASAKUSA_HOME}

command.* = com.asakusafw.yaess.basic.BasicCommandScriptHandler
command.*.resource = asakusa
#command.*.env.HADOOP_CMD = /usr/bin/hadoop
command.*.env.ASAKUSA_HOME = ${ASAKUSA_HOME}

## multi-threaded job scheduler (requires asakusa-yaess-paralleljob plug-in)
#scheduler = com.asakusafw.yaess.paralleljob.ParallelJobScheduler
#scheduler.parallel.default = 3
#scheduler.parallel.hadoop-master = 1

### remote execution via SSH (requires asakusa-yaess-jsch plug-in)
hadoop = com.asakusafw.yaess.jsch.SshHadoopScriptHandler
hadoop.ssh.user=hadoop
hadoop.ssh.host=hishidama-hadoop
hadoop.ssh.port=22
hadoop.ssh.privateKey=${HOME}/.ssh/id_dsa
hadoop.ssh.passPhrase=hishidama-ssh-password
hadoop.resource = hadoop-master
hadoop.env.HADOOP_CMD = /home/hadoop/bin/hadoop
hadoop.env.ASAKUSA_HOME = /home/hadoop/asakusa

#command.* = com.asakusafw.yaess.jsch.SshCommandScriptHandler
#command.*.ssh.user=asakusa
#command.*.ssh.host=localhost
#command.*.ssh.port=22
#command.*.ssh.privateKey=${HOME}/.ssh/id_dsa
#command.*.ssh.passPhrase=
#command.*.resource = asakusa
#command.*.env.HADOOP_CMD = /usr/bin/hadoop
#command.*.env.ASAKUSA_HOME = ${ASAKUSA_HOME}

設定内容はWindGateのプロファイルのresource.hadoopと同様。


Direct I/Oの設定

Exporter用のDirect I/Oのプロパティーファイルを定義する。
これはHadoopクラスター側の設定となるので、src/dist/hadoopというディレクトリーを作成し、その下にファイルを置いておく。
Hadoopクラスターに配置する為のAsakusaアーカイブを作る際にsrc/dist/hadoopの下のファイルを含めるようにする)

src/dist/hadoop/core/conf/asakusa-resources.xml:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
	<property>
		<name>com.asakusafw.runtime.core.Report.Delegate</name>
		<value>com.asakusafw.runtime.report.CommonsLoggingReport</value>
	</property>

	<property>
		<name>com.asakusafw.directio.hadoop</name>
		<value>com.asakusafw.runtime.directio.hadoop.HadoopDataSource</value>
	</property>
	<property>
		<name>com.asakusafw.directio.hadoop.path</name>
		<value>hadoop</value>
	</property>
	<property>
		<name>com.asakusafw.directio.hadoop.fs.path</name>
		<value>/tmp/directio/example</value>
	</property>
</configuration>

これは普通のDirect I/Oの定義と同じ。

今回の例ではhadoopという名前で定義している。
ここではfs.pathに「/tmp/directio/example」というローカルのディレクトリーを指定しているが、
実際のHadoopクラスターが対象であれば「hdfs://〜」というHDFSのパスになるだろう。


Asakusaアプリケーションのビルドおよび配置

AsakusaアプリケーションをビルドしてAsakusaアーカイブを作り、実行するサーバーに配置(デプロイ)する。

  1. ビルド
    1. まずはビルド(コンパイル)を行う。
      $ cd Asakusaプロジェクト
      $ ./gradlew clean compileBatchapp
  2. WindGateサーバー用
    1. WindGateサーバー用アーカイブを作成する。
      $ ./gradlew attachBatchapps attachConfGateway assembleAsakusafw
    2. 作成されたbuild/asakusafw-0.6.1.tar.gzをWindGateサーバー(asakusaユーザー)に転送する。
    3. Asakusaアーカイブを解凍する。
      $ cd /home/asakusa
      $ mkdir asakusa
      $ cd asakusa
      $ tar xf ~/asakusafw-0.6.1.tar.gz
  3. Hadoopクラスター(マスターノード)用
    1. Hadoopクラスター用アーカイブを作成する。
      $ ./gradlew attachBatchapps attachConfHadoop assembleAsakusafw
    2. 作成されたbuild/asakusafw-0.6.1.tar.gzをマスターノード(hadoopユーザー)に転送する。
    3. Asakusaアーカイブを解凍する。
      $ cd /home/hadoop
      $ mkdir asakusa
      $ cd asakusa
      $ tar xf ~/asakusafw-0.6.1.tar.gz

gradlewコマンドの引数のattachConfGatewayやattachConfHadoopがポイント。
attachConfGatewayだとsrc/dist/gatewayの下のファイルがアーカイブに含まれ、
attachConfHadoopだとsrc/dist/hadoopの下のファイルがアーカイブに含まれる。

※compileBatchappとattachは別々に行う必要がある。WindGateサーバー用とHadoopクラスター用でAsakusaアプリケーションのビルドバージョンを一致させる必要がある為。


実行

まずは入力データを用意する。

今回の例ではWindGateサーバー上に入力データとなるCSVファイルを用意する。
今回はWindGateプロファイルのresource.local.basePathが「/tmp/windgate」でImporterのgetPath()が「input/example.csv」なので、
WindGateサーバー上の「/tmp/windgate/input/example.csv」が入力ファイルとなる。

/tmp/windgate/input/example.csv:

abc,def
foo,bar

実行はWindGateサーバー(asakusaユーザー)上で行う。

$ export ASAKUSA_HOME=$HOME/asakusa
$ cd $ASAKUSA_HOME
$ yaess/bin/yaess-batch.sh ExampleBatch

これで、実行が成功すればHadoopクラスター側(HDFS上)にファイルが出力される。

$ hadoop fs -ls /tmp/directio/example/output
Found 1 items
-rwxrwxrwx 1 hadoop hadoop 18 2014-03-29 11:07 /tmp/directio/example/output/example0000.csv

$ hadoop fs -cat /tmp/directio/example/output/example0000.csv
abc,def
foo,bar

core/conf/asakusa-resources.xmlのcom.asakusafw.directio.〜.fs.pathが「/tmp/directio/example」でExporterのgetResourcePattern()が「output/example*.csv」なので、
HDFS上(今回はスタンドアローンなので実際はローカルファイルシステム上だが)に「/tmp/directio/example/output/example0000.csv」が作られる。


なお、最初は環境設定まわりで色々エラーが出るだろうから、ドライランを指定して実行するのがよい。

$ yaess/bin/yaess-batch.sh ExampleBatch -D dryRun 2>&1 | tee /tmp/log.txt

実行時エラー

実行しようとした際によく出るエラーについて。


環境変数HADOOP_CMDを定義していない

which: no hadoop in (/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/asakusa/bin)
〜
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/cli/CommandLineParser
	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2442)
	at java.lang.Class.getMethod0(Class.java:2685)
	at java.lang.Class.getMethod(Class.java:1620)
	at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:492)
	at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:484)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.cli.CommandLineParser
	at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
〜

YAESSはhadoopコマンドの場所を元にしてHadoopのライブラリーを取得する。
上記のエラーメッセージは、hadoopコマンドが見つからないのでHADOOP_HOMEが特定できず、
HADOOP_HOME/libの下にあるCommandLineParserのjarファイルを読み込めていない為に発生している。

hadoopコマンドの場所は環境変数HADOOP_CMDで指定する。
(環境変数HADOOP_HOMEを定義するのでも構わないのだが、HADOOP_HOMEは非推奨となっているのでなるべく使わない)

$ export HADOOP_CMD=/home/hadoop/bin/hadoop

$ ls $HADOOP_CMD …ちゃんと見えることを確認する

もしくは、hadoopコマンドにパスを通せばよい。


ローカルの環境変数JAVA_HOMEを定義していない

Error: JAVA_HOME is not set.
WindGate failed with exit code: 1

YAESSでは環境変数JAVA_HOMEを参照するので、定義しておく必要がある。

$ export JAVA_HOME=/usr/java/default

WindGateのリモートの環境変数JAVA_HOMEを定義していない

2014/03/29 10:34:04 INFO [WG-HADOOP_FS-I30004] Remote command started: ASAKUSA_HOME="/home/hadoop/asakusa" _ASAKUSA_APP_EXECUTION_MODE="simulation" _ASAKUSA_APP_BATCH_ID="ExampleBatch" HADOOP_CMD="/home/hadoop/bin/hadoop" _ASAKUSA_APP_BUILD_ID="7670f5b8-85ce-4a17-8a86-468e3c78e5ec" "/home/hadoop/asakusa/windgate-ssh/libexec/put.sh" (resource=hadoop, target=hadoop@hishidama-hadoop:22) [ExampleBatch|ExampleJob]
com.asakusafw.windgate.hadoopfs.ssh.WindGateHadoopPut
Error: JAVA_HOME is not set.
com.asakusafw.windgate.hadoopfs.ssh.WindGateHadoopPut failed with exit code: 1
〜
2014/03/29 10:34:04 ERROR [WG-HADOOP_FS-E14001] Failed to exit command (resource=hadoop, process=in, path=[target/hadoopwork/012447d7-5648-4cba-83af-4bf3abd97340/ExampleBatch/ExampleJob/prologue/windgate/in]) [ExampleBatch|ExampleJob]
2014/03/29 10:34:04 ERROR [WG-CORE-E05003] Failed to close drain driver: in local->hadoop [ExampleBatch|ExampleJob]
java.io.IOException: SSH connection returns unexpected exit code: (code=1, process=in:drain)
	at com.asakusafw.windgate.hadoopfs.ssh.AbstractSshHadoopFsMirror$SshDrainDriver.close(AbstractSshHadoopFsMirror.java:426) ~[na:na]
	at com.asakusafw.windgate.core.process.BasicProcessProvider.execute(BasicProcessProvider.java:99) ~[asakusa-windgate-core-0.6.1.jar:na]
〜

WindGateで接続する先のサーバーにも環境変数JAVA_HOMEを定義しておく必要がある。
(リモート(今回の例ではHadoopクラスターのマスターノード)の/etc/bashrcとかに書いておけば読み込まれる)

これはWindGateのプロファイルに記述しておくことも出来る。

ASAKUSA_HOME/windgate/profile/gateway.properties(src/dist/gateway/windgate/profile/gateway.properties):

resource.hadoop.env.JAVA_HOME=/usr/java/default

YAESSのリモートの環境変数JAVA_HOMEを定義していない

2014/03/29 10:42:58 INFO [YS-JSCH-I00004] Opened SSH command channel: user=hadoop, host=hishidama-hadoop, port=22, id=/home/asakusa2/.ssh/id_dsa, executable=/home/hadoop/asakusa/yaess-hadoop/libexec/hadoop-execute.sh, elapsed=148ms
Starting Asakusa Hadoop:
 Hadoop Command: /home/hadoop/bin/hadoop
    App Library: /home/hadoop/asakusa/batchapps/ExampleBatch/lib/jobflow-ExampleJob.jar
       Batch ID: ExampleBatch
        Flow ID: ExampleJob
   Execution ID: e4a77444-9478-4ce5-a376-b7d5f6028b84
          Class: com.example.batchapp.exampleBatch.exampleJob.directio.epilogue.StageClient
Error: JAVA_HOME is not set.
YAESS Hadoop failed with exit code: 1
〜
2014/03/29 10:42:58 ERROR [YS-CORE-E04001] Job "epilogue.directio" execution was failed: batchId=ExampleBatch, flowId=ExampleJob, executionId=e4a77444-9478-4ce5-a376-b7d5f6028b84, phase=epilogue, jobId=epilogue.directio, serviceId=hadoop, trackingId=YAESS/ExampleBatch/ExampleJob/epilogue/e4a77444-9478-4ce5-a376-b7d5f6028b84/epilogue.directio
com.asakusafw.yaess.basic.ExitCodeException: Unexpected exit code from Hadoop job: code=1 (batch=ExampleBatch, flow=ExampleJob, phase=epilogue, stage=epilogue.directio, exection=e4a77444-9478-4ce5-a376-b7d5f6028b84)
	at com.asakusafw.yaess.basic.ProcessHadoopScriptHandler.execute0(ProcessHadoopScriptHandler.java:278) ~[asakusa-yaess-core-0.6.1.jar:na]
	at com.asakusafw.yaess.basic.ProcessHadoopScriptHandler.execute(ProcessHadoopScriptHandler.java:206) ~[asakusa-yaess-core-0.6.1.jar:na]
〜

YAESSで接続する先のサーバーにも環境変数JAVA_HOMEを定義しておく必要がある。
(リモート(今回の例ではHadoopクラスターのマスターノード)の/etc/bashrcとかに書いておけば読み込まれる)

これはYAESSのプロパティーファイルに記述しておくことも出来る。

ASAKUSA_HOME/yaess/conf/yaess.properties(src/dist/gateway/yaess/conf/yaess.properties):

hadoop.env.JAVA_HOME=/usr/java/default

ローカルとリモートのAsakusaアプリケーションが異なる

com.asakusafw.runtime.core.context.InconsistentApplicationException: Inconsistent application, please check your deployed application: url="jar:file:/home/hadoop/asakusa/batchapps/ExampleBatch/lib/jobflow-ExampleJob.jar!/META-INF/asakusa/application.properties", batchId="ExampleBatch", caller="7670f5b8-85ce-4a17-8a86-468e3c78e5ec", callee="ed992636-1bc7-4d76-b937-7101d800d04f", hostname="192.168.1.24 38515 192.168.1.23 22"
	at com.asakusafw.runtime.core.context.RuntimeContext.verifyBuildId(RuntimeContext.java:366)
	at com.asakusafw.runtime.core.context.RuntimeContext.verifyApplication(RuntimeContext.java:317)
	at com.asakusafw.runtime.stage.BaseStageClient.run(BaseStageClient.java:120)
	at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:65)
〜

ローカル(今回の例ではWindGateサーバー)とリモート(今回 の例ではHadoopクラスターのマスターノード)にAsakusaアプリケーションを配置するが、
YAESSは実行前にそれらのバージョンが同じかどうかをチェックしており、ビルドバージョンが違っていたらエラーになる。

Asakusaアプリケーションをビルドしたら、双方のサーバーにAsakusaアプリケーションを配置しなおす必要がある。


入力ファイルが無い

2014/03/29 10:21:11 ERROR [WG-STREAM-E03001] Failed to open input stream: /tmp/windgate/input/example.csv (resource=local, process=in) [ExampleBatch|ExampleJob]
java.io.FileNotFoundException: /tmp/windgate/input/example.csv (そのようなファイルやディレクトリはありません)
	at java.io.FileInputStream.open(Native Method) ~[na:1.7.0_45]
	at java.io.FileInputStream.<init>(FileInputStream.java:146) ~[na:1.7.0_45]
	at com.asakusafw.windgate.stream.file.FileInputStreamProvider.openStream(FileInputStreamProvider.java:78) ~[asakusa-windgate-stream-0.6.1.jar:na]
〜

単なる入力ファイルの作り忘れ^^;
WindGate(CSV)の場合はローカルファイルを扱うことになるので、ログに表示されているパスは素直にローカルファイルシステム上の場所となる。


WindGateへ戻る / AsakusaFW目次へ戻る / 技術メモへ戻る
メールの送信先:ひしだま