バッチ処理の標準化仕様
jBatch登場
バッチ処理の標準化仕様が、JavaEE7で初めて導入された。その背景には、近年Webアプリケーション環境の分散化とホスト系技術者の減少が顕著なことから、ホスト中心であったバッチ処理をWebアプリケーションへ移行することで、運用コストの増大を抑えようとする動きがある。
標準化される以前にも、Javaでは自作したスレッドによるバッチ処理の実装が可能であった。しかし、その実装はベンダー固有の仕様や独自のフレームワークに基づくため、他言語で実装されたバッチ処理をJavaへ移行する際の障壁になっていた。
バッチ処理に関する規定は長い間、定められていなかったが、JSR352 Batch Application for the Java Platform(以下、jBatch)により、バッチ処理の標準化仕様がJava EEに盛り込まれた。jBatchはSpring Batchのアーキテクチャを参考に開発された、Javaでバッチ処理を実行するためのフレームワークである。jBatchという標準化された手法により、今まで困難とされてきたバッチ処理の移行も容易に開発・実施できるようになった。
そこで本稿ではjBatchの構成要素を紹介し、さらにWebSphere Application Server Liberty Profile(以下、Liberty)上での実装方法、および高可用性を実現するトポロジーについて解説する。
jBatchの構成要素
ジョブとステップ
図表1は、jBatchのバッチ処理アーキテクチャである。バッチ処理のメインとなる機能は「ジョブ」と「ステップ」である。ジョブは複数のステップから構成され、ジョブオペレータによって実行され、結果はジョブリポジトリに格納される。
ジョブの処理全体の流れはXML形式で記載され、そのXMLはJob Specification Language(以下、JSL)と呼ばれる。ジョブの各処理はステップで実装する。ステップには3つの要素があり、入力となるデータの取得をItemReader、データの変換やビジネスロジックの実行をItem Processor、データの出力をItemWriterがそれぞれ担当する。
開発者はこれらの要素に対して、jBatchで用意されたインターフェースを実装し、クラスを作成する。ジョブオペレータはジョブやリポジトリの操作といったジョブの制御を実行し、ジョブリポジトリは実行されたジョブの履歴を保持する。このように、各々の機能を明確に分けることで、jBatchはバッチアプリケーションの変更に対して柔軟に対応する。
ジョブの実行順序制御
ジョブは各ステップの実行結果に応じて、次の処理を決定する。その遷移要素には、次のステップを実行するnextと、ジョブを中止するfail、stop、endがある。正常終了を示すのがendであり、failは異常終了、stopは中断を示す。
ステップの流れを決める要素として、jBatchではフロー、スプリット、デシジョンの各要素を定義している(図表2)。
フローは複数のステップをまとめたもので、フロー内部で定義されているステップは同じフロー内のステップにのみ遷移できる。スプリットは複数のフローを並行して処理し、フローはスプリットの分岐先として定義される。スプリットで定義された各フローは異なるスレッドで処理されるので、処理時間を短縮できる。デシジョンは次の処理の判断をカスタマイズする機能であり、各ステップの終了状態から、より詳細な判断ロジックを定義できる。
以上の仕組みにより、jBatchは複雑な分岐をもつジョブに対応する。
可用性や冗長性の実現
jBatchは障害時の影響を抑え、より効率的にステップを実行するための機能を備えている。
ステップには、チャンク型とバッチレット型の2種類がある。チャンク型は複数データの連続処理に、バッチレット型は単体で完結する処理に用いられる。前述したItemReader、ItemProcessor、ItemWriterの定義が必要なのはチャンク型であり、バッチレット型はBatchletインターフェースを実装したクラスで完結する。
チャンク型ステップのシーケンスを図表3に示す。チャンク型ステップは、一連の処理を繰り返す場合に用いられる。特徴は、入力データの読み込み(ItemReader)とロジックの処理(ItemProcessor)は1件ずつ実行するのに対し、結果の出力(Item Writer)は一定回数まとめて出力することである。
処理は一括するほど効率的だが、障害発生時の手戻りも多くなる。そのためチャンク型ステップでは、ある程度まとめて書き込み、障害発生時の手戻りを抑えるように実装されている。各々の書き込むタイミングを「チェックポイント」と呼び、障害発生時には、直前に書き出された内容から再開できる。チェックポイントのインターバルや頻度は、システム全体のパフォーマンスに大きく影響するので、適切なタイミングで実施する必要がある。
さらにjBatchは、ステップ内部の処理を並行して実行する「ステップパーティション」と呼ばれる機能を備えている。各スレッドに処理が分割され、独立して動作させられる点はスプリットと同じであるが、スプリットが異なるフローを並列処理するのに対し、ステップパーティションは同一のステップを並行処理する点に違いがある。ステップパーティションは後述するLibertyの機能と組み合わせて実行することで、バッチ処理のさらなる可用性や冗長性を実現する。
ジョブの実行と管理
jBatchではジョブオペレータがジョブを実行するが、その呼び出し方法に関する規定はない。ジョブオペレータを呼び出し、ジョブを実行するクラスは開発者が作成する。
しかしjBatchはバッチコンテナ上で実行されるので、javaのmainメソッドからは実行できない。そのためJAX-RSやJSF、EJBなどを用いて、ジョブの実行クラスを呼び出す必要がある。図表4に、ジョブの呼び出し経路の例を示した。
また、バッチを決められた時間に実行する機能もjBatchでは定義されていないので、必要な場合は各自でcronなどのジョブスケジューラと連携させねばならない。バッチアプリケーションの実行には、こうした開発が必要となる。
これに対して、以下に紹介するLibertyではジョブを実行するためのコマンドインターフェースが用意されているので、ジョブ実行のプログラムを作成する必要はない。
さらに障害復旧後にチェックポイントから再開させる場合、ジョブを再実行する必要があるが、それにはIDが求められる。ジョブは実行時にジョブインスタンスIDが割り振られ、ジョブがエラーで中断したり、中断が指示された場合は、そのジョブインスタンスIDにより再実行を指示することで再開させる。こうした各ジョブの状態や履歴に関する情報は、すべてジョブリポジトリに保存される。
LibertyによるjBatchの実装
Libertyはバージョン8.5.5.6以降、Javaバッチの実行環境としてjBatchをサポートしている。LibertyはjBatchをスムーズに運用し、耐障害性を考慮したシステム構築に向けて以下の機能を実装する。
・ 独自のジョブ操作インターフェース
・ 複数サーバー構成のサポート
・ ロールベースのセキュリティ
・ ジョブログの実装
ここでは、上記のうちジョブの運用を容易にするジョブ操作インターフェース、高可用性を実現する複数サーバー構成のサポートについて紹介する。セキュリティやジョブログについては、以下を参照されたい。
独自のジョブ操作インターフェース
前述したように、ジョブの実行にはジョブを実行するクラスと、そのクラスを呼び出す仕組みが必要である。しかしLibertyでは、ジョブを操作するためのインターフェースが提供されており、ジョブ実行クラスやそのクラスを呼び出す仕組みを開発者が独自に作成しなくても、ジョブを容易に実行できる。
それには、以下の2つの方法がある。いずれも最終的にはジョブオペレータにアクセスし、ジョブを操作する。
・ RESTによる操作
・ batchManagerコマンドによる操作
RESTによるジョブの実行では、Basic認証に必要な情報とjsonでの情報の受け渡しのために、リクエストヘッダにAuthorizationとContent-Typeを追加する。リクエストボディには図表5のように、アプリケーション名、モジュール名、JSL名、プロパティなど、実行したいジョブの情報を追加する。このリクエストを以下のURLへPOSTで送信すると、IDとともに結果が返される。
https://<host>:<port>/ibm/api/batch/jobinstances/
図表6に、URL送信後のレスポンス例を示す。ただしこの状態では、ジョブの実行完了は示されておらず、サブミットした結果がIDとともに返信されるのみである。最終的な実行結果の確認は、ジョブのステータスを問い合わせるためのURLを別途送信する必要がある。
さらにLibertyではbatchManagerと呼ばれる、RESTクライアントを実装したコマンドラインツールを用意しており、Libertyの動作環境があれば、コマンドでジョブを操作できる。batchManagerコマンドはsubmit、stop、restartといった操作を示す必須パラメータと、RESTのリクエストヘッダやボディに相当するパラメータをオプションとして指定することで実行する。図表7は、ジョブの実行例である。
このようにLibertyのジョブ操作インターフェースを用いることで、開発者はジョブのロジック開発のみに専念でき、開発の負担を軽減できる。ただしスケジューリング機能はLibertyにもサポートされないので、定期的なジョブの実行方法は別途考慮する必要がある。
複数サーバー構成のサポート
Libertyによるバッチ環境の構築に際しては、Libertyにより提供される機能、ユーザーが開発する機能、前提となる機能がある。
Libertyにより提供される機能
・ ディスパッチャ
・ キュー
・ エグゼキュータ
ユーザーが開発する機能
・ バッチアプリケーション
・ JSL
前提となる機能
・ JVM環境(Liberty)
・ ジョブリポジトリ
高可用性や拡張性が求められる場合、Libertyではリクエストを受け付けるディスパッチャと、処理を実行するエグゼキュータに役割を分離する。
図表8は、1つのディスパッチャと2つのエグゼキュータで構成した例である。ジョブのリクエストは、まず前段のディスパッチャが受け、ディスパッチャからエグゼキュータへの振り分けはキューを介して実行する。また、ディスパッチャとエグゼキュータはすべて同じジョブリポジトリを共有させることで一貫性をもたせる。
さらにステップパーティションを使用する場合、図表9のように、パーティション化されたジョブ専用にエグゼキュータを分離することも可能である。ジョブが実行され、複数パーティションに分割されたら、各分割ジョブのメッセージをキューに渡し、そのキューからメッセージを受けたパーティション処理用のエグゼキュータがパーティションを実行する。
なおパーティションエグゼキュータも通常のエグゼキュータと同様に、ジョブリポジトリは共有させる。
jBatchでの高可用性設計
最後に、バッチ処理を実行するサーバーの配置とトポロジー、それぞれのメリットとデメリットについて解説する。
高可用性トポロジー
ディスパッチャやエグゼキュータは複数台配置することで、高可用性や拡張性を高められる。ディスパッチャの並行稼働には、RESTでのリクエストを振り分ける負荷分散装置が必要となる。ここでは負荷分散に、Webサーバーを採用する。Webサーバーは、プラグインによりリクエストを適切なLibertyに割り振れるし、Webサーバー自体も並行稼働が可能である。
Libertyのバッチ実行環境には、前述のディスパッチャとエグゼキュータがあるが、それぞれの役割に応じて別のLibertyが担当することも、同一のLibertyで実行させることも可能である。役割で分散させずにバッチを実行させた構成①が、図表10である。この構成ではキューは不要で、最もシンプルな高可用トポロジーである。
さらに、ディスパッチャとエグゼキュータで処理を分割させ、それぞれで冗長構成をとる構成を検討してみよう。ただし、各コンポーネント間の冗長構成には制限があり、ディスパッチャとキュー間の1:N構成、キューとエグゼキュータ間のN:1構成は実行できない。またキューにメッセージングエンジンを採用した場合、メッセージングエンジンの高可用性はLibertyではサポートされていない。
これらの制限を考慮して構築できる構成②が、図表11となる。ディスパッチャとエグゼキュータは複数構成であるが、キューが単体構成となるので、キューについては単一障害点(SPOF)となる。
またバッチ処理にパーティションを含む場合、パーティション専用のエグゼキュータを別途用意する構成も考えられる(図表12)。パーティション専用のエグゼキュータも複数台構成が可能だが、メインの処理を担うエグゼキュータとメッセージを介するキューは単体構成となる。
各トポロジーのメリットとデメリット
①と②の構成を比較すると、以下のようなメリットとデメリットがある(図表13)。
①の構成はシンプルだが、ジョブの分散がプラグインに依存し、Libertyサーバーダウン時の影響が②に比較すると大きい。これに対して②の構成は、サーバーダウン時の影響や負荷分散の点では①に比べると有利であるが、SPOFの生じる点がデメリットとなる。
複数台構成での実行環境は、現時点ではまだ少ない。しかしバッチ処理が大規模化するにつれ、バッチ環境でも高可用性の求められるケースが今後は増加すると考えられる。
以上、jBatchによるバッチ処理の構成要素とLibertyでの実装、さらに高可用性を実現するトポロジーについて解説した。Javaを用いたバッチ処理にも標準仕様が登場したことで、今まで移行が困難とされてきた独自のフレームワークや実装から解放され、アプリケーション開発の生産性向上が実現する。
さらにLibertyを用いることで複数台構成にも対応し、大規模かつ高負荷なバッチ処理でも、高い可用性や冗長性を実現できる。開発生産性の向上と高可用性を併せもつJavaバッチシステム構築に向け、jBatchとLibertyを検討してはどうだろうか。
著者|小松英之
日本アイ・ビー・エム システムズ・エンジニアリング株式会社
クラウド・ソリューション クラウド・プラットフォーム
アドバイザリーITスペシャリスト
2002年、日本アイ・ビー・エム システムズ・エンジニアリングに入社。WebSphere Application Serverを中心とした技術サポートを担当し、ワークショップ講師、記事執筆などの活動に従事している。