Javaバッチの実行環境 EEなのかSEなのか

この記事は Java EE Advent Calendar の13日目です。
昨日は @yamadamn さんの WebLogic Server 12.2.1のThreadLocal Clean Out機能を検証してみる #javaee #jpoug - yamadamn’s blog でした。
明日は @den2sn さんです。

バッチの実行環境について書こうと思います。

はじめに

JSR 352: Batch Applications for the Java Platform として仕様が定義されたJavaバッチですが、仕様書*1を見てみると、SE環境、EE環境の両方で使えるように設計されていることが明記されています。

3. Forward
It is designed for use on both the Java SE and Java EE platforms.

6. Applicability of Specification
This specification applies to Java SE and Java EE environments. It requires Java 6 or higher.

実際、たとえば、特定のEEサーバと結びついていないSpringBatchもWildFlyのモジュールとして登録してEE環境で使うなんてこともできるようです。逆に、WildFlyに同梱されているJBeretも、jberet-seというサブモジュールを使うことで単独でSE環境において使用可能になっていたりするようです。*2

では、SE環境、EE環境それぞれで、構成はどんな感じになるのでしょうか?メリット、デメリットは?
簡単に以下まとめてみました。

SE環境

mainメソッドからJobOperator経由で叩く形になります。この辺はSpringBatchならCommandLineJobRunner、JBeretならそのものズバリ Main というクラスが標準で同梱されているので、そのまま使ってしまうのが楽です。以下の絵ではステップの中身をreader/processor/writer形式としていますがbatchletでもよいです。

SEと言っているので当然ですが、EEサーバ上ではなく、素のコマンドライン実行となります。1ジョブ単位でJVMを起動〜停止することになります。


EE環境

EEサーバ上にEARなりWARなりでデプロイして稼働します。JobOperator経由で叩くというのは変わりませんが、何かしら起動契機を作ってあげる必要があります。薄いServletを作ってHTTPリクエストに応じて起動させるというのが一番わかりやすそうです。

EEサーバ上ですので、JVMはサーバ起動中はずっと上がっていることになります。


(番外)オンラインバッチ

JSR352とは関係ありませんが、EE環境を考えるときにしばしば比べられる、いわゆるオンラインバッチも合わせて示します。
見た目の構成としては、HTTPリクエストを受けてレスポンスを返す、Webアプリケーションそのものです。ヒープサイズなど基盤面の設定として、大量データ処理に耐えられるようバッチ向けのチューニングをすることになります。


比較

メリット、デメリットの比較です。ほんのいくつかの観点を取り上げただけで、全然網羅的ではありませんが、考えるきっかけとしてとらえて頂ければと思います。

SE環境 EE環境 オンラインバッチ
起動契機の作りこみ ○不要 △必要 △必要
JVM起動オーバーヘッド △1ジョブごと ○無視できる ○無視できる
強制停止 ○1ジョブごとにkillすればよい ×サーバごと落とさざるを得ないことがある ×サーバごと落とさざるを得ないことがある
学習コスト △かかる △かかる ○従来のWebアプリと同じ

オーバーヘッドについては、SE環境の場合1ジョブごとにJVMを起動しなければならず、起動オーバーヘッドが気になるというのはよく言われるところかと思いますが、実際バッチの場合そこまで大容量のライブラリを読み込むわけでもなく*3、従来COBOL等で書いていたようなベタなファイル処理であればあまり問題にならないようです。準リアルタイム的な処理が必要な場合問題になり得ますが、それはそれでオンラインバッチ型で作ってしまう方が慣れていて楽そうですし、本当にストリーム処理レベルのことが必要ならそもそもバッチではなく専用ミドルウェア*4を入れる方がよさそうです。

バッチの運用をしているとどうしても大量のデータの流入などでジョブのロングランとなり、強制停止せざるを得ない場面が発生します。SE環境の場合であれば1ジョブごとに落とすだけで済むのですが、EE環境の場合がやっかいで、最悪EEサーバごと落とすしか無く、その場合サーバ上で稼働していた全アプリが巻き添えになってしまいます。*5

ここまでを見ると、EE環境で動かすことのメリットが無いように思えてしまいます。
EJBをはじめとする他のEE機能との連携でメリットが生まれてくるとか、EE環境で動かすことでオンラインバッチには無い機能面のメリットがあるなら別ですが、いまのところあまり思いつきません。*6

まとめ

「JSR352はSE環境で動かすのがよい」が現時点で個人的な結論です。

こんな場合はEE環境の方がメリットがあるんじゃないか、というパターンがあればコメントとかTwitterでつっこみいただけると嬉しいです。

*1:https://jcp.org/en/jsr/detail?id=352

*2:jbatch RIをSE環境で使うのは、DI実装と切り離されちゃっているので可能だけど若干つらそうな印象でした。 http://yoshio3.com/2014/02/18/jbatchjsr-352-on-java-se-%E7%92%B0%E5%A2%83/ http://kencharos.hatenablog.com/entry/2015_adv_cal_4_jbatch

*3:EEサーバ立ち上げ時に読み込むJARライブラリ群の数や容量と比べて。

*4:StormとかSpark Streamingとか

*5:バッチ停止の方法としては、JobOperatorのstopメソッド経由でいわゆるgraceful stopが可能ですが、即時止まることを保証するものではありません。即時止めようとするとどうしてもkill、ということになります。

*6:唯一浮かんだのは、バッチ版microserviceというか分かりませんが、1 EEサーバ上に単一バッチアプリ、のような構成が可能なら、強制停止のデメリットがなくなって、使いやすくなるかも、というぐらい。