Java Batch 仕様 (Public Review時点)
-
Upload
norito-agetsuma -
Category
Documents
-
view
24.547 -
download
14
description
Transcript of Java Batch 仕様 (Public Review時点)
Java Batch
Java EE
7Java EE 7から加わるバッチ仕様Batch Applications for the Java Platform - JSR 352
Java Batch
Batch Applications for the Java Platform (JSR 352)
Java EE 7から導入されるバッチフレームワーク Spring Batch のアーキテクチャを踏襲 アーキテクチャ定義のもと、APIとXMLの仕様を定義
JSR352 の構成 (Public Review時点)
ジョブXML仕様(第5章)
アーキテクチャ仕様 Job/Step/Chunk(第4章)
API仕様(第6章)
アーキテクチャ全体像を定義
アーキテクチャを『どうやって』実装するか
Java Batch
Java Batchの主な機能1 - 実行順序制御
ジョブXMLと呼ばれる設定で、処理手順を定義する 処理の分岐、グループ化、並列実行が可能
STEP1STEP2-1
Flow (ステップ グループ化)
STEP2-2
Decision(条件分岐)STEP3-1
Split
FlowFlow
FlowSplit (ステップの並行実行)
start
end
Java Batch
Java Batchの主な機能2 - 分割コミット
レコード数が多い場合は、チェックポイントは必須要件 後述するchunk処理方式によって分割コミットを実現
start endcommit▼
commit▼
commit▼
10行処理 10行処理 10行処理×
障害発生
ロールバックは最終コミットまで
Java Batch
Java Batchの主な機能3 - エラーハンドリング
バッチ失敗のよくある原因は不正な入力データ Java Batch ではエラーレコードを自動スキップする
バッチプログラム…
1, AAA, BBB, CCC2, DDD, EEE, FFF???,,,,aaa,,aeae, 3, JJJ, KKK, LLL
99, ZZZ, ZZZ, ZZZ
スキップ
Java Batch
Java Batchの主な機能4 - 並行・分散実行
仕様上は明記されていないが、分散実行も可能? 引数にExternalizableを持つAPIがいくつかある (オブジェクトのシリアル化を意識している)
Server A
Server B
Server CSTEP1
STEP2-1 STEP2-2
STEP3-1 STEP3-2
Java Batch
ジョブスケジューラ と JavaBatch
ジョブスケジューラ(cron/JP1/Tivoliなど) Java Batch
スケジューリング(時刻・周期起動)
ジョブ実行順序管理JP1:ジョブネット
JavaBatch:ジョブXMLジョブ実装サポート(フレームワーク)
実行権限の管理
Java Batchには、cronのような時刻起動する機能はない cronやJP1から、Java Batchを呼び出して使う 順序管理のように被る領域もある (使い分け整理が必要)
ジョブスケジューラ(Cron/JP1など)
Java Batch
Java Batch の位置付け
OS/Java VM
Servlet JPA Java Batch
アプリケーションサーバ (JBoss等)
ユーザ作成のアプリケーション
各種APIの提供時刻起動
起動元は従来からあるバッチスケジューラ バッチAPの開発を簡単にするAPI提供がJava Batchの役割
データベース
ファイル(CSV/XML 等)
Java Batch
Java EE
7アーキテクチャ
Java Batch
アーキテクチャ
JobOperator STEP1STEP2-1
STEP3 STEP4
JobRepository
STEP2-1
Job
JCLやCOBOLディベロッパに馴染み深いアーキテクチャ バッチ処理をメインフレームからJavaに移管させるため、 昔からある考え方をベースとした。
Java Batch
ジョブ
JobOperator STEP1STEP2-1
STEP3 STEP4
JobRepository
STEP2-1
Job
バッチ階層の最上位要素 複数のステップを組み合わせてジョブを構成する ステップ全体に関わる設定はジョブに定義する (例 : リスタート制御)
Java Batch
ジョブをXMLで表現すると
<job id="samplejob" restartable="false"> <step id="step1" next="step2" /> <step id="step2" /></job>
ジョブの識別子。JobOperator経由で起動時に
このidを指定する。
Java Batch
ジョブをXMLで表現すると
<job id="samplejob" restartable="false"> <step id="step1" next="step2" /> <step id="step2" /></job>
ジョブがリスタート可能か。デフォルトはtrueのオプション属性。
(リスタートについては後述)
Java Batch
ジョブをXMLで表現すると
<job id="samplejob" restartable="false"> <step id="step1" next="step2" /> <step id="step2" /></job>
処理したいステップを定義。Next属性で次のステップを指定。
(順序制御は色々種類があるので、後で詳しく解説)
Java Batch
ジョブインスタンスの考え方
Job
JobInstance
JobExecution
*
*
『ファイル取り込み』ジョブ
2007/05/05 に実行する『ファイル取り込み』ジョブ
2007/05/05 に実行する『ファイル取り込み』ジョブ の1回目
JobInstance1日1回のジョブであれば、毎日1つずつ生成される。次の日にリスタートする場合は、前日のインスタンスを使う。
JobExecution実行ごとに生成される。リスタート時には新たに生成される。
JobExecution
JobInstance
Java Batch
ジョブとリスタート 1つのジョブインスタンスは、データとの対応を持つ 例えば、1月1日のジョブインスタンスは、1月2日に リスタートしても1月1日分のデータにアクセスする。
対象データが違うため、前日のリスタートジョブと 当日のジョブは並行実行することも可能。
JobInstance
JobExecution
*
JobExecution
1月1日分のジョブ
1/1のデータ1/2のデータ1/3のデータ
◎△×
1/1 1回目の実行
1/2 リスタート実行
リスタート時も1/1分
のデータを処理
実行インスタンスは実行毎に生成
Java Batch
ステップ
JobOperator STEP1STEP2-1
STEP3 STEP4
JobRepository
STEP2-1
Job
ジョブに含まれるタスクを定義する。 各ステップの内容は、ユーザがコーディングする。 図のように、条件によって分岐することもできる。
Java Batch
ステップ : 2つの処理方式 Chunk 方式 Batchlet方式
STEP ItemReader ItemProcessor ItemWriter batchlet
execute()read()item
process(item)
itemwriter(item)
ExitStatus
STEP
execute()
ExitStatus
process()
ExitStatus
Chunk方式 Batchlet方式
Java Batch
Chunk方式 大規模なデータ処理に適した処理方式 1件ずつ読み込んで処理するのでメモリ消費を抑える コミット間隔の調整もしやすい
STEP ItemReader ItemProcessor ItemWriter
execute()read()item
process(item)
itemwriter(item)
ExitStatus
Chunk = 出力の塊 を示す複数レコードを処理して一度に出力することも可能である。(詳細は次スライドで紹介)
Java Batch
Chunk方式 : まとめてコミット
STEP ItemReader ItemProcessor ItemWriter
execute() read()item
process(item)
item
writer(items)
ExitStatus
read()item
process(item)
item
1アイテム目の読み込みと処理
2アイテム目の読み込みと処理
処理が終わった2アイテムを書き込み、コミット
オーバヘッド低減のため、書き込みはまとめることも可能。(chunk-size属性の設定)
Java Batch
Chunk方式 : アノテーション
@Namedpublic class MyItemReader { @ReadItem MyBatchInputRecord read() throws Exception { // レコード読み取り処理 }}
ItemReader のコード例
SpringBatchはインタフェースをベースに作成するが、JavaBatchでは、@ReadItemのようにアノテーション対応。
Reader/Processor/Writerはユーザがコード作成する。
Java Batch
Chunk方式 : CDIとの連携
@Namedpublic class MyItemReader { @ReadItem MyBatchInputRecord read() throws Exception { // レコード読み取り処理 }}
ItemReader のコード例
全てのコンポーネントに、@java.inject.Namedが必要。ジョブXMLからコンポーネント名を指定するため。
JavaBatchではSpringDIの代わりにCDIが使われる
Java Batch
Chunk方式 : ジョブXML例
<job id="samplejob" restartable="false"> <step id="step1" next="step2" > <chunk reader="MyReader" processor="MyProcessor" writer="MyWriter" chunk-size="2" /> </step> <step id="step2" /></job>
ステップの子要素としてchunkを定義する reader/processor/writer属性にはクラス名を定義 チャンクサイズの設定もXMLで可能 (デフォルトは10)
Java Batch
Batchlet方式 ファイル/DB処理ではないステップに使う ファイル圧縮・転送・各種OSコマンドの実行 など Spring Batchのtaskletを同等のもの
batchletSTEP
execute()
ExitStatus
process()
ExitStatus
Chunkと比べて非常にシンプル。STEPとbatchletが1対1となる。
Java Batch
Batchlet方式 : @Process
@Namedpublic class MyBatchLet{ @Process String process() throws Exception {...} @Stop void stopMe() throws Exception {...}}
@Processを付けたメソッドに処理を記述するだけ
@Stop JobOperator#stop()されたときにコールバックされる
@Process バッチレットの処理内容を定義する
Java Batch
Batchlet方式 : ジョブXML例
<job id="samplejob" restartable="false"> <step id="step1" next="step2" />
<batchlet ref="MyBatchlet" /> </step> <step id="step2" /></job>
ステップの子要素としてbatchletを定義する batchletを実装したクラス名を参照先として設定する
Java Batch
リスナ : ジョブ・ステップ実行前後にコールバック
ジョブやステップの実行前後に呼び出される 一時ディレクトリ掃除・再生成などの前準備に使える 複数のリスナを定義することが可能
STEP1STEP2-1
STEP3 STEP4STEP2-1
Job
liste
ner
liste
ner
liste
ner
liste
ner
ジョブレベルリスナ(ジョブ実行前)
ジョブレベルリスナ(ジョブ実行後)
ステップレベルリスナ(ジョブ実行前後)
Java Batch
JobOperator
JobOperator STEP1STEP2-1
STEP3 STEP4
JobRepository
STEP2-1
Job
ジョブはジョブオペレータにより起動/再起動/停止される バッチ処理のコントロール役
Java Batch
JobOperator : API
// factoryでインスタンスを取得JobOperator jobOperator = BatchRuntime.getJobOperator(); // ジョブIDを指定して、ジョブを起動jobOperator.start("jobid1", property);
BatchRuntimeクラスからインスタンスは取得できる 先ほどXMLで指定したジョブIDを起動のキーとする
<job id="jobid1">
Java Batch
JobRepository
JobOperator STEP1STEP2-1
STEP3 STEP4
JobRepository
STEP2-1
Job
ジョブやステップの実行状態を保存する 保存された状態にはJobOperator経由でアクセスする 前述した、リトライ用のジョブインスタンスはここに保存
Java Batch
Java EE
7実行順序の制御
Java Batch
ステップ実行手順は複数の手段がある
STEP1STEP2-1
Flow (ステップ グループ化)
STEP2-2
Decision(条件分岐)STEP3-1
split
Flow
FlowFlow
split (ステップの並行実行)
start
end
Flow - ステップのグループ化 Sprit – 並行実行するフローの組み合わせを定義 Decision – ステップの終了ステータスに応じた条件分岐
Java Batch
もっともシンプルなケース
STEP1start
STEP2end
1つのジョブに、ステップが順処理で2つ
<job id="samplejob"> <step id="step1" next="step2" /> <step id="step2" /></job>
next属性に次ステップを指定。idが対象。
Java Batch
Flow ステップを一連のユニットとしてまとめる フローが終了したあとは、次エレメントに遷移(ステップ、スプリット、デシジョン、他のフローのいずれか)
start
STEP1 STEP2-1 STEP2-1
FlowSTEP3
end
<job id="samplejob"> <step id="step1"> <flow id="flow1" next="step3"> <step id="step2-1"/> <step id="step2-2"/> </flow> <step id="step3" /></job>
フローの中に複数ステップを定義。next属性には、フローが完了したあとの次のステップを定義する。
Java Batch
Split : 3つの構成要素
start
split
Flow
FlowFlow
splitanalyzer
end
STEP2
Split : 並列実行するフローの組み合わせを定義 Split Collector :
フロー実行結果を受け取り Split Analyzer に送る。 Split Analyzer :
Split Collectorから受け取った並行実行結果を処理する。
Split Collector
Split Collector
Split Collector
Java Batch
Split : ジョブXMLの書き方 スプリットの中に並列実行したいフローを定義する 各フローは別々のスレッドで実行される
<job id="samplejob"> <split id="split1" next="step2"> <flow id="flow1"> <step id="step1-1-1" next="step1-1-2"/> <step id="step1-1-2"/> </flow> <flow id="flow2"> <step id="step1-2-1" next="step1-2-2"/> <step id="step1-2-2"/> </flow> </split> <step id="step2" /></job>
Java Batch
Split Collector
start
split
FlowFlow
Flow
splitanalyzer
end
STEP2
Split Collector
Split Collector
Split Collector
フロー結果をスプリットアナライザに中継する役割 各スプリットしたフローの実行スレッドで動作 FlowContextからデータを集め、Externalizableで返す
FlowContextで受け渡し Externalizableで
受け渡し
Java Batch
Split Collector : @CollectSplitData@Namedpublic class SplitCollector { @BatchContext FlowContext flowContext;
@CollectSplitData Externalizable collectSplitData() throws Exception { // コンテキストからFlowデータの取得 FlowData flowData = flowContext.getTransientUserData();
// Externalizable実装のユーザクラスを生成 ExternalizableBookData serial = new ExternalizableBookData(); serial.setName(flowData.getBookName());
// Externalizableを返す return serial; }}
コンテキストは自動的にインジェクションされる
Split Collector を示すアノテーション
外部化(Externalizable)の結果を返す
Memo.仕様書には『The FlowContext is in scope when this method receives control.』とあるが、Split Collectorがどうやって各スプリットの結果を受け取るかはうまく読み取れていない。読み取れる範囲からは、上記のようにコンテキストからデータ取得すると思われる。
Java Batch
参考 : java.io.Externalizable Serializableを継承したインタフェース オブジェクトの外部出力を自分でコーディングする。public class Book implements Externalizable {
String title; int price;
public Book() {}
public Book(String title, int price) {this.title = title; this.price = price;
}
@Overridepublic void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(title); out.writeInt(price);}
@Overridepublic void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {title = in.readUTF(); price = in.readInt();
}}
引数なしコンストラクタを忘れると復元時に InvalidClassException が投げられるので注意。
書き出し処理
復元処理
Java Batch
Split Analyzer
start
split
Flow
FlowFlow
splitanalyzer
end
STEP2
Split Collector
Split Collector
Split Collector
Split Collectorから並行実行したフロー結果を集約する。 Collectorと異なり、シングルスレッドで動作する。 Collectorからデータが送られるたびに複数回起動する。
ファイル DBMS
Split Collectorから各フロー結果を受け取る
集約・分析結果を出力
Java Batch
Split Analyzer : @AnalyzeCollectorData
@Namedpublic class SplitAnalyzer { @BatchContext SplitContext splitContext;
@AnalyzeCollectorData void analyze(Externalizable data) throws Exception{ // SplitCollectorから受け取ったデータを分析 }
@AnalyzeStatus void analyzeStatus(String batchStatus, String exitStatus) throws Exception { // スプリットの終了ステータスに応じた処理を行う }}
SplitContextにアクセスできる
Collectorから受け取ったデータを分析。Collectorが書き出し回数分繰り返し呼ばれる。(3スプリットであれば、3回呼ばれる)
バッチステータスやスプリットの終了コードに応じた処理を定義する。
Memo.仕様書には『The analyzeCollectorData method receives control each time a Partition collector sends its payload.』と書かれていて、この解釈をCollectorからデータが送られるたびに毎回起動されると解釈した。一方、Analyzerはシングルスレッド起動としても明記されているため、一度に複数のCollectorからデータが送られた場合の挙動が仕様書からはうまく読み取れていない。
Java Batch
CollectorとAnalyzer : ジョブXMLの書き方
<job id="samplejob"> <split id="split1" next="step2"> <flow id="flow1"> <step id="step1-1-1" next="step1-1-2"/> <step id="step1-1-2"/> </flow> <flow id="flow2"> <step id="step1-2-1" next="step1-2-2"/> <step id="step1-2-2"/> </flow> <collector ref="SplitCollector" /> <analyzer ref="SplitAnalyzer" /> </split> <step id="step2" /></job>
Splitエレメントの子エレメントとして定義。参照先の実装クラス名をrefに指定する。
Java Batch
Decision
start
STEP1Decision
exit status
STEP2
end
×
<next on=”*” to=”STEP2”>
<fail on=”fail step”>
<end on=”stop step”>
異常終了
ステップ・フロー・スプリットの終了ステータスをもとに 次の遷移先を選択する。
全部で4種類の遷移を指定できる<next> : 次エレメントへ遷移 <end> : 正常終了<fail> : 異常終了 <stop> : 一時停止
Java Batch
バッチステータス と 終了ステータス バッチステータス
ジョブ全体の現在の状態を定義するパラメータ 状態の種類は仕様で定義されている バッチランタイムにより設定される
終了ステータス ジョブ・ステップ・フロー・スプリットの終了ステータス 文字列値をユーザで定義する ユーザが設定する。
何も設定されていない場合は、バッチステータスと同じ値。
STEP1start
STEP2end
Stepexit status
Batch Status (バッチ全体の現在の状態)
Stepexit status
Job exit status
Desicionの判定対象
Java Batch
終了ステータスの設定方法 コンテキストのAPIで設定する リスナーで設定すると、Chunk処理と分離できて便利@Namedpublic class StepListener { @BatchContext StepContext stepContext;
@BeforeStep public void beforeStep() throws Exception { // なんらかの前処理をする }
@AfterStep public void afterStep() throws Exception { if (stepContext.getException() instanceof InvalidRecordException) { stepContext.setExitStatus("failed cause invalid records"); } }}
Stepから特定の例外が投げられた場合に終了ステータスを設定する。
Memo.仕様書にはリスナのコンテキストについて言及されていない。ステップ・リスナにはステップ・コンテキストがインジェクションできると思うが、上記のコードは推測の域である。
Java Batch
参考 : バッチステータス一覧
ステータス値 意味
STARTINGバッチジョブは、ジョブオペレータのでスタートまたはリスタート操作されると、バッチランタイムによりSTARTING状態とされます。ステップにおいても、実行開始直前はSTARTING状態となります。
STARTED バッチジョブがバッチランタイムにより既に開始されている状態です。ステップにおいても、一度実行された後はSTARTED状態となります。
STOPPINGバッチジョブが、ジョブオペレータの停止操作、またはジョブXMLの<stop>エレメントによって停止要求された状態です。ステップにおいても、STOPPING状態となった場合は、バッチランタイムによりまもなく停止処理が行われます。
STOPPEDバッチジョブが、ジョブオペレータの停止操作、またはジョブXMLの<stop>エレメントによって停止した状態です。ステップにおいても、バッチランタイムに停止された場合、STOPPED状態となります。
FAILED バッチジョブが、未解決の例外、またはジョブXMLの<fail>エレメントによって終了した状態です。ステップにおいても同様の条件でFAILED状態となります。
COMPLETED バッチジョブが、正常終了、またはジョブXMLの<end>エレメントによって終了した状態です。ステップにおいても同様の条件でCOMPLETED状態となります。
ABANDONEDバッチジョブが、ジョブオペレータの『放棄(avandoned)』操作が行われたことを示す状態です。放棄状態のジョブはジョブオペレータ経由で確認することはできますが、実行やリスタートを行うことはできません。履歴閲覧を目的に確認できるようになっています。
Java Batch
Decision : @Decide
@Namedpublic class Decider { @Decide public String decide(BatchContext context) throws Exception {
String exitStatus = context.getExitStatus(); if ("SUCCESS".equals(exitStatus)) { return "SKIP"; } return exitStatus; }}
メソッド引数でコンテキストを取得する 終了コードを判定し、条件に応じて終了コードを上書き
終了コードが SUCCESS の場合、SKIP に上書きする。
Java Batch
Decision : ジョブXMLの書き方
<job id="samplejob"> <step id="step1"> <decision id="decision1" ref="Decisider"> <next on="SKIP" to="step3"/> <next on="*" to="step2"/> </decision> </step> <step id="step2" next="step3"/> <step id="step3"></job>
refにはDeciderのクラス名を設定
DeciderからSKIPが返された場合はstep3に進む。それ以外はstep2に進む。
Decisionではスキップの決定など動的な遷移制御ができる。
Java Batch
実行順序の制御 : まとめ
STEP1STEP2-1
Flow (ステップ グループ化)
STEP2-2
Decision(条件分岐)STEP3-1
split
FlowFlow
Flowsplit (ステップの並行実行)
start
end
ジョブXMLとAPIを駆使して、様々な遷移が可能 主な手段として Flow、Decision、Split の3種類がある。
Java Batch
Java EE
7例外ハンドリング
Java Batch
バッチ失敗の原因 : 不正なレコード
Name, Age, Address山田, 29, 千葉佐藤, 46, 埼玉
破壊,,aaa,,99,,,
...(数万行続く...)
処理対象のファイル
不正なレコートが1行あっただけで、バッチ全体が失敗する
バッチプログラム
SUCCESSSUCCESSSUCCESSFAIL
Status FAIL
Java Batch
バッチ失敗の原因 : 一時的に繋がらない
Max Session = 200
DBセッションが一時的に足りないだけで、翌日に再実行。
100 Session
ジョブA
ジョブC
ジョブB
90 Session
×一時的な過負荷によりDBセッション数が足りない
Java Batch
バッチ失敗の原因 : パーミッションがない
ディレクトリや一時ファイルの作成に失敗する。
バッチプログラム(一般ユーザ)
root権限のディレクトリ
パーミッション744のディレクトリ
×一般ユーザ拒否
×
一時ファイル
mkdir
グループ書き込み権が足りない
Java Batch
Java Batch 3つのエラーハンドリング
スキップ 不正な入力データをスキップして、処理を継続 Chunk方式のステップが対象
リトライ 一時的な要因により失敗した処理を再実行 セッション不足、ロック待ち など
リスタート 深刻なエラーが発生した場合はジョブを失敗させる 原因を取り除き、手動で再起動する
Java Batch
スキップ
ItemReaderName, Age, Address
破壊,,aaa,,99,,,
田中, 25, 東京ItemProcessor
ItemWriter
1. 例外発生
JavaBatchランタイムスキップ対象例外
InvaliedRecordException
xxx Exception
△△△ Exception
2.例外スロー
3.スキップ許可
Java Batchには次レコードにスキップしても良い例外を登録 (ジョブXMLに例外クラス名を記述)
ItemReaderから投げられた例外がスキップ対象か判定する。 デフォルトは例外が1つでも発生すると、ジョブは失敗する
不正レコードを含んだ入力ファイル
Chunk方式
山田, 29, 千葉
佐藤, 54, 埼玉4. スキップ
Java Batch
スキップ : <skippable-exception-classes>
<job id="samplejob" restartable="false"> <step id="step1" next="step2" > <chunk reader="MyReader" processor="MyProcessor" writer="MyWriter" skip-limit="10"> <skippable-exception-classes> <include class="java.io.IOException" /> <exclude class="java.net.SocketException" /> </skippable-exception-classes> </chunk> </step> <step id="step2" /></job>
スキップ上限数を設定
スキップ対象の例外を設定。子クラスも対象になるので、
excludeで除外対象も要指定。
デフォルトは1つでも例外発生した時点でジョブ失敗。必ずスキップ対象例外を設定すること。ファイル全体が不正なものに備えて、スキップ上限数も必ず設定する。
Java Batch
スキップリスナ : @OnSkipedReadItem
どのレコードをスキップしたのか記録することは重要 スキップ契機のリスナーであるスキップリスナでロギング
@Namedpublic class SkipListener {
private static final Logger logger = Logger.getLogger(SkipListener.class);
@OnSkipReadItem public void onSkipReadItem(Exception ex) throws Exception {
// エラーメッセージのロギング logger.log(ex.getMessage()); }}
Java Batch
スキップリスナ : ジョブXMLの書き方
<job id="samplejob" restartable="false"> <step id="step1" next="step2" > <chunk reader="MyReader" processor="MyProcessor" writer="MyWriter" skip-limit="10"> <skippable-exception-classes> <include class="java.io.IOException" /> <exclude class="java.net.SocketException" /> </skippable-exception-classes> </chunk> <listeners> <listener ref="SkipListener" /> </listeners> </step> <step id="step2" /></job>
スキップリスナはステップ階層のリスナとして登録する。
ref属性にはクラス名を指定。
Read Item
Java Batch
ItemProcessorで例外が発生したら?
Read ItemRead Item
Process
Write Item
Cash Item
Process
Process
chunk size分読み込み<chunk chunk-size=”x”>
ロールバック
トランザクション区間
Cash Item
Cash Item
チャンクサイズ分、まとめて読み込まれる。 例外発生するとチャンク全体をロールバック。 読み込み済キャッシュは再利用される。
Java Batch
ItemProcessor例外 : スキップ方法
スキップRead ItemRead ItemRead Item
Process
Write Item
Cash Item Process
トランザクション区間
Cash Item
Cash Item
▲commit
キャッシュからロード
キャッシュからアイテムをロードして再処理 例外の原因となったアイテムはスキップする
Java Batch
ItemWriterで例外が発生したら?
Read ItemRead ItemRead Item
Process
Write Item
Cash Item Process
Cash Item
Cash Item Process
ロールバック
@WriteItemswriteItems(List<T> items);
???
Writerは処理したデータをまとめて受け取る どの入力がエラーの原因になったのかわからない→ スキップ対象のItemを特定しにくいのが特徴
Java Batch
ItemWriter例外 : スキップ方法
Read ItemRead ItemRead Item
Process
Cash Item Process
Cash Item
Cash Item Process
Write Item
Write Item
Write Item
▲commit
▲commit
× 例外アイテム
スキップ
1アイテムずつトランザクションを分ける
1アイテムずつキャッシュから読み込み処理 例外が発生したアイテムをスキップする
→ Processorと異なり、再度例外発生させてスキップ
Java Batch
リトライ 一時的な原因の例外に対して効果的 (ネットワーク不安定/DBロック待ち など)
リトライを繰り返すと、性能に影響を与えるので注意 チャンク単位でリトライする
Read ItemProcess
Write ItemCash Item
ProcessCash ItemProcessCash Item
Read ItemRead Item
インターネット
×
WebServiceProcess
Write ItemCash Item
ProcessCash ItemProcessCash Item
接続失敗
成功
チャンク単位でリトライ
外部のWebサービスは繋がりにくい場合もあるので、リトライが効果的
Java Batch
リトライ : <retryable-exception-classes>
<job id="samplejob" restartable="false"> <step id="step1" next="step2" > <chunk reader="MyReader" processor="MyProcessor" writer="MyWriter" retry-limit="3"> <retryable-exception-classes> <include class="javax.xml.ws.soap.SOAPFaultException" /> <exclude class="xxxException" /> </retryable-exception-classes> </chunk> </step> <step id="step2" /></job>
リトライ回数を設定
リトライ対象の例外を設定。子クラスも対象になるので、
excludeで除外対象も要指定。
retry-limitを設定しない場合、デフォルトではリトライし続ける。必ずretry-limitに値を設定すること。
Java Batch
リトライリスナ : @OnRetryWriteException
スキップと同様に、リトライもロギングが重要 リトライリスナをユーザが実装してロギングする
@Namedpublic class RetryListener {
private static final Logger logger = Logger.getLogger(RetryListener.class);
@OnRetryWriteException public void onRetryWriteException(List<T> items,Exception ex) throws Exception {
// エラーメッセージのロギング logger.log(ex.getMessage()); }}
Java Batch
リトライリスナ : ジョブXMLの書き方
リトライリスナはステップ階層のリスナとして登録する。
ref属性にはクラス名を指定。
<job id="samplejob" restartable="false"> <step id="step1" next="step2" > <chunk reader="MyReader" processor="MyProcessor" writer="MyWriter" skip-limit="10"> <retryable-exception-classes> <include class="javax.xml.ws.soap.SOAPFaultException" /> <exclude class="xxxException" /> </retryable-exception-classes> </chunk> <listeners> <listener ref="RetryListener" /> </listeners> </step> <step id="step2" /></job>
Java Batch
リトライとスキップを組み合わせる リトライとスキップは通常組み合わせて設定する 例: 3回リトライして、失敗する場合は10回までスキップ
<job id="samplejob" restartable="false"> <step id="step1" next="step2" > <chunk reader="MyReader" processor="MyProcessor" writer="MyWriter" retry-limit="3" skip-limit="10"> <retryable-exception-classes> <include class="javax.xml.ws.soap.SOAPFaultException" /> </retryable-exception-classes> <skippable-exception-classes> <include class="javax.xml.ws.soap.SOAPFaultException" /> </skippable-exception-classes> </chunk> </step> <step id="step2" /></job> 同じ例外をretryable-exception-classesと
skippable-exception-classesに設定する
リトライ回数 スキップ上限数
Java Batch
リスタート
STEP1 STEP2 STEP3STEP3 STEP4
STEP3STEP3 STEP4
対向システムからファイル取得
解凍 集計処理
集計処理
次システムへ集計データ転送
次システムへ集計データ転送
×ディスクフル発生
リスタート(STEP3から再開)
失敗したステップから再開する機能 スキップやリトライで対処できない問題に対応 (オペレータが手を入れないと治らない問題)
チャンク処理内でのリスタートも可能
Java Batch
allow-start-if-complete の設定 業務によっては、ステップを1からやり直したい ジョブXMLへの設定で、ステップが完了していた場合に 再実行するか設定ができる
STEP1
STEP2
STEP3
STEP2
STEP3
STEP1
途中から再開(デフォルト) 最初から再開
<step id="step1" allow-start-if-complete="true">
<step id="step1" allow-start-if-complete="false">
Java Batch
リスタート : ジョブXML
<job id="samplejob" restartable="true"> <step id="step1" next="step2" start-limit="5" /> <step id="step2" next="step3" allow-start-if-complete="false"/> <step id="step3" /></job>
リスタート可能か?(オプション。デフォルトtrue)
リスタート上限回数
完了していても再実行時に動かすか
restartable属性 : ジョブごとにリスタート可能か設定 Start-limit属性 : ステップごとにリスタート上限数を設定
Java Batch
エラーハンドリングのポイント
堅牢とは 少々のエラーデータが混じっていても落ちない 一時的なエラーであれば自動的に復旧 オペレータの手をかけないバッチが堅牢なバッチ
Java Batch が提供する手段 スキップ : 不正データのスキップ リトライ : 一時的なエラーに対する自動再試行 リスタート : 途中から再開することで、再実行コスト低減
いかに『堅牢なバッチ』を作るかがポイント
Java Batch
Java EE
7あとがき
Java Batch
2013年上半期に仕様はfinalへ
Public Reviewをもとに調査した 2013/1 現在は前述した仕様群は作業中 仕様確定に向けて、まだ内容は修正される可能性も
Java EE 7 へ盛り込みへ 次のJava EE 仕様である『7』に盛り込まれる予定 Java EE 7 も2013年内にはリリース予定 EE 7 - GlashFishリリースまで、SpringBatchとの差分調査は難しい
Javaで大規模バッチ構築のために、期待する標準です。