自分が必要なところだけ。
(image)と書いてある部分は本家を見てください。
3.1 Job
このセクションではバッチジョブのコンセプトに関連する定形について説明します。Jobとはバッチ処理全体をカプセル化したエンティティです。他のSpringプロジェクトでお馴染みのように、JobはXMLないしJavaのコンフィギュレーションに記述します。このコンフィギュレーションは「ジョブコンフィギュレーション」として参照されます。しかし、Jobは全階層のトップにすぎません。
(image)
Spring Batchでは、Jobは単にStepのコンテナです。flowとして結合した複数のStepを結合し、リスタートのような全ステップへ適用されるプロパティを設定します。
(image)
job設定は下記を含みます。
- ジョブの名前
- Stepの定義と処理順
- ジョブがリスタート可能か
Jobのデフォルト実装はSpring BatchのSimpleJobクラスで提供されています。Jobに基本的な機能を備えていますが、直接インスタンス化されるのを避けるためabstractになっています。
3.1.1 JobInstance
JobInstanceは論理的ジョブ実行のコンセプトに関連しています。1日の終りに1回実行するバッチジョブを例にあげます。(上記ダイアグラムの’EndOfDay’参照)
‘EndOfDay’ジョブが1つ存在しますが、各Jobの実行は独立して行われます。
このジョブに関して言えば、1つの論理的JobInstanceが各日付に存在します。例えば、1/1の実行と1/2の実行があるわけです。もし1/1の実行が1度失敗した場合、次の日にもう1回実行されます。これはまだ1/1の実行となります(通常これは対応するデータにも同じことが言え、1/1の実行は1/1の対象データに対して行われます。)そのため、各JobInstanceは複数回の実行を行いうることになり(JobExecutionについては以降で詳述します)、JobおよびJobParametersに対応するJobInstance1つだけが1度の処理で実行されます。
JobInstanceの定義は取得されるデータとは全く関係がありません。データをどのように取得するかはItemRewaderで実装すべき部分です。例えば、EndOfDayのシナリオでは、 ‘effective date’や’schedule date’のようなカラムデータが存在するとします。1/1の実行では1日の、1/2の実行では2日のデータを取得します。この決定が企業意思のようなものであるため、ItemReaderが決定を担うべきなのです。
しかし、同じJobInstanceを使用することで決定されるものは前の実行からの「状態」(例えば後述するExecutionContext)なのです。新しいJobInstanceを使用することは「最初から始める」ことを意味し、存在するインスタンスを使用することは一般に「中断したところから始める」ことを意味するのです。
3.1.2 JobParameters
JobInstanceがJobと違うところについて議論したところで、「1つのJobInstanceを他のものと区別しているものはなんであるか」という疑問が湧いてきます。その答えがJobParametersです。JobParameterはバッチジョブを開始する際に使用されるパラメータの集合です。これらはJobInstance特定と実行時の参照に利用されます。
(image)
上記の例では1つのJobしか存在しませんが、1/1と1/2の実行を行う2つのインスタンスが存在し、パラメータが2008/01/01から始まるものと2008/01/02に始まるものが存在します。この制約は「JobInstance = Job + 特定のJobParameters」と定義できます。これにより、開発者はどのパラメータを扱うかを決めれば良くなるため、JobInstanceを効率的に定義しやすくなります。
3.1.3 JobExecution
JobExecutionはJobを実行するための技術的コンセプトに関連しています。1回の実行は失敗か成功をもって終了しますが、各実行における対応するJobInstanceはその実行が成功しない限り完了しません。EndOfDayでいうと、2008/01/01のJobInstanceの1度目の実行が失敗した場合、同一のパラメータでもう一度実行されれば、新しいJobExecutionが作成されますが、JobInstanceは同一です。
Jobはそのジョブがなんであるかとどのように実行されるかを定義します。JobInstanceは純粋に正確なリスタートをできるよう実行をグループ化しているものです。対してJobExecutionは、実行時に何が行ったのかを記録し、それ自体が操作、生成されたプロパティを保持するものです。
JobExecutionプロパティ
名称 | 説明 |
---|---|
status | BatchStatusオブジェクト(STARTED, FAILED, COMPLETED) |
startTime | 実行開始時刻 |
endTime | 実行終了時刻(成否にかかわらず) |
exitStatus | 実行結果 |
createTime | JobExecutionが最初に生成された時刻 |
lastUpdated | JobExecutionが存続している最新の時刻 |
executionContext | 実行の間に保持すべきデータ |
failureExceptions | ジョブ実行時に発生した例外。ジョブが失敗した際に複数の例外が発生した時に利用。 |
これらのプロパティは1つの実行のステータスを確定するのに使用される重要なものです。例えば、EndObDayの1/1の実行が21:00に実行されて21:30に失敗した場合、バッチのメタデータテーブルには下記データが出来ます。
BATCH_JOB_INSTANCE
JOB_INST_ID | JOB_NAME |
---|---|
1 | EndOfDayJob |
BATCH_JOB_EXECUTION_PARAMS
JOB_EXECUTION_ID | TYPE_CD | KEY_NAME | DATE_VAL | IDENTIFYING |
---|---|---|---|---|
1 | DATE | schedule.Date | 2008-01-01 | TRUE |
BATCH_JOB_EXECUTION
JOB_EXEC_ID | JOB_INST_ID | START_TIME | END_TIME | STATUS |
---|---|---|---|---|
1 | 1 | 2008-01-01 21:00 | 2008-01-01 21:30 | FAILED |
ジョブが失敗し、原因特定に丸一夜かかったとしましょう。翌日に1/1のジョブが投げられて21:30に成功し、1/2のジョブも実行されなければならないため21:31にじっこうされ、22:30に完了したとします。ここでは1つのJobInstanceしか実行されていません。そうでなければ2つのジョブが同一データにアクセスしてデータベースのデッドロックが発生してしまう可能性があります。これはジョブが実行されるときにスケジューラが決めることです。別々のJobInstanceであるために、Spring Batchは同時実行されるのを防ぐことはできないのです。(1つのJobInstanceを実行しようとしたところに同一JobInstanceを実行しようとするとJobExecutionAlreadyRunningExceptionがthrowされます。)JobInstanceに1行データが作成され、JobParametersとJobExecutionテーブルに2行データが作成されます。
BATCH_JOB_INSTANCE
JOB_INST_ID | JOB_NAME |
---|---|
1 | EndOfDayJob |
2 | EndOfDayJob |
BATCH_JOB_EXECUTION_PARAMS
JOB_EXECUTION_ID | TYPE_CD | KEY_NAME | DATE_VAL | IDENTIFYING |
---|---|---|---|---|
1 | DATE | schedule.Date | 2008-01-01 | TRUE |
2 | DATE | schedule.Date | 2008-01-01 | TRUE |
3 | DATE | schedule.Date | 2008-01-02 | TRUE |
BATCH_JOB_EXECUTION
JOB_EXEC_ID | JOB_INST_ID | START_TIME | END_TIME | STATUS |
---|---|---|---|---|
1 | 1 | 2008-01-01 21:00 | 2008-01-01 21:30 | FAILED |
2 | 1 | 2008-01-02 21:00 | 2008-01-02 21:30 | COMPLETED |
3 | 2 | 2008-01-02 21:31 | 2008-01-02 22:29 | COMPLETED |
4.Jobの設定と実行
Jobオブジェクトは単にstepのコンテナに見える一方、開発者が気をつけるべき多くの設定オプションが存在します。さらに、どのようにJobが実行されるかとどのようにメタデータが実行中に保存されているかについても多くの注意点があります。この章ではJob様々な設定オプションと実行時の注意について説明します。
4.1 Jobの設定
Jobインターフェースにはいくつかの実装がありますが、名前空間で設定の違いを認識します。必須の依存関係は3つだけで、名前、JobRepository、そしてStepのリストのみです。
この例はstepを生成するのにparent bean definitionを利用しています。特定のstepを宣言する他のオプションについてはstep configurationの章を参照してください。XML名前空間はデフォルトで’jobRepository’というリポジトリを参照しますが、以下のようにオーバーライドできます。
stepに加え、ジョブ設定は他の要素を含有しえます。並列化を設定する
4.1.1 再実行性
バッチジョブを実行するにあたっての1つの鍵となる問題が、Jobをリスタートした場合の挙動です。Jobを起動した際にJobInstanceに対するJobExecutionが既に存在する場合は「リスタート」として扱われます。JobExecutionが既に存在したとしても全てのJobが起動するのが理想的なのですが、それができない場合もあります。その場合に新たなJobInstanceを生成するかは開発者に委ねられますが、Spring Batchでは楽に設定ができます。Jobがリスタートされてはならず、新たなJobInstanceとして実行されるべきである場合、restartableプロパティをfalseにします。
...
4.2 Java Config
Spring 3でXMLに代わりJavaでアプリケーションを設定できるようになりました。Spring Batch 2.2.0からバッチジョブをJavaで設定できるようになりました。Javaベースの設定には2つのコンポーネントが存在します。@EnableBatchConfigurationと2つのbuilderです。
@EnableBatchConfigurationは他の@Enable~アノテーションと同様の動作をします。この場合、@EnableBatchConfigurationはバッチジョブを構築する基本的な設定を提供します。この設定では、他のautowired可能な多くのbeanに加えてStepScopeが生成されます。
- JobRepository – bean name “jobRepository”
- JobLauncher – bean name “jobLauncher”
- JobRegistry – bean name “jobRegistry”
- PlatformTransactionManager – bean name “transactionManager”
- JobBuilderFactory – bean name “jobBuilders”
- StepBuilderFactory – bean name “stepBuilders”
この設定の中核となるインターフェースはBatchConfigurerです。デフォルトの実装では上記のbeanを提供し、DataSourceを要求します。このデータソースはJobRepositoryで使用されます。
基本的な設定ができれば、ユーザーはジョブの設定のためにbuilder factoryを使用することができます。以下がJobBuilderFactoryとStepBuilderFactoryを使用した例です。
@Configuration
@EnableBatchProcessing
@Import(DataSourceCnfiguration.class)
public class AppConfig {
@Autowired
private JobBuilderFactory jobs;
@Autowired
private StepBuilderFactory steps;
@Bean
public Job job() {
return jobs.get("myJob").start(step1()).next(step2()).build();
}
@Bean
protected Step step1(ItemReader reader, ItemProcessor processor, ItemWriter writer) {
return steps.get("step1")
. chunk(10)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
@Bean
protected Step step2(Tasklet tasklet) {
return steps.get("step2")
.tasklet(tasklet)
.build();
}
}
4.3 JobRepositoryの設定
先述したように、JobRepositoryはJobExecutionやStepExecutionにおける様々なSpring Batch上のドメインオブジェクトをCRUD操作するのに使用されます。これはJobLauncher, Job, Stepなど多くの要素が要求します。バッチ名前空間がJobRepositoryと他のものを区別しますが、いくつか設定オプションが利用可能です。
上記オプションのうちid以外は必須ではありません。設定されなかった場合は上記のデフォルトが使用されます。
4.4 JobLaucherの設定
JobLaucherインターフェースの最も基本的な実装はSimpleJobLaucherです。これは実行可能にするためにJobRepositoryのみを依存関係として要求します。
一度JobExecutionが獲得されると、Jobの実行メソッドまで渡されます。最終的には呼び出し元にJobExecutionが返ります。
(image)
スケジューラから起動した場合、シーケンスは直行して上手く動作します。しかし、HTTPリクエストからの起動した時に問題が発生することがあります。このような場合、起動は非同期で行う必要があり、そうすることでSimpleJobLaucherは即座に呼び出し元にreturnします。これは、バッチプロセスなどを長時間実行し続ける間HTTPリクエストをオープンし続けるのは良くないからです。シーケンス例は下記のとおりです。
(image)
SimpleJobLaucherは上記のようなシナリオの場合、下記のように簡単に構成できます。
TaskExecutorインターフェースの実装は、どのようにジョブが非同期で実行されるかについてコントロールします。
4.5 ジョブの実行
バッチジョブの起動には最低2つのものが必要です。起動されるJobとJobLaucherです。両方が同じコンテキストにあっても違っても構いません。例えば、もしジョブをコマンドラインから起動する場合、新しいJVMがジョブごとに起動します。そのため、個々のJobがJobLauncherを持ちます。一方、もしHttpRequestのスコープからウェブコンテナから起動した場合、通常非同期のジョブに設定された1つのJobLauncherがあり、ジョブの実行のために複数のリクエストを送ります。
4.5.1 コマンドラインからの実行
エンタープライズスケジューラからジョブを実行したいユーザーである場合、コマンドラインが第一のインターフェースになります。これは、ほとんどのスケジューラで(QuartzでNativeJobを使用しない場合を除く)主にシェルスクリプトから起動してOSのプロセスとして直接動作します。Javaプロセスをシェルスクリプト以外から起動する方法もたくさんあります(Perl,Ruby,mavenなどビルドツールも)。しかし、殆どの人はシェルスクリプトに馴染んでいるため、例はこちらにフォーカスします。
CommandLineJobRunner
ジョブを起動するスクリプトはJVMを起動しなければならないため、エントリポイントとしてmainメソッドを有するクラスが必要になります。Spring
Batchにはその目的のための実装があります。CommandLineJobRunnerです。気をつけるべきは、これはアプリケーション起動の方法の1つでしか無く、他にも方法はたくさんあり、この方法が最高のものではないということです。CommandLineJobRunnerは4つのタスクを実行します。
- 適切なApplicationContextをロードします。
- コマンドライン引数をJobParametersにパースします。
- 引数に応じた適切なジョブを配備します。
- アプリケーションコンテキストから得たJobLauncherを使用してジョブを起動します。
すべてのタスクは実行時の引数のみで達成されます。要求される引数は以下のとおりです。
引数名 | 説明 |
---|---|
jobPath | ApplicationContextを生成するのに必要なXMLファイルの場所。このファイルにジョブ実行のため必要なすべての情報が含まれてなければならない。 |
jobName | 実行するJobの名前 |
この引数はjobPathが最初、次にjobNameが来なければなりません。この後に続くすべての引数はJobParametersとして認識され、「name=value」のフォーマットで記述されなければなりません。
[bash]
bash$ java CommandLineJobRunner endOfDayJob.xml endOfDay schedule.date(date)=2007/05/05
[/bash]
jar内に記述されたマニフェストを使用したい場合、クラスは直接使用されます。ここでの例ではdomain
sectionで使った’EndOfDay’の例を使用します。第1引数はJobを含むApplicationContextである’endOfDayJob.xml’です。第2引数はジョブ名を表す’endOfDay’です。最後の引数は、JobParametersに変換される’schedule.date(date)=2007/05/05’です。XMLコンフィギュレーションの例は以下のとおりです。
本来Spring Batchはもっと多くを要求するのでこの例はシンプル過ぎますが、ここでは2つの主なCommandLineJobRunnerの必須事項であるJobとJobLauncherを提供しています。
コメント