こんにちは。平田です。
JBoss EAP 7からHAシングルトンデプロイが復活したので試してみました。
JBoss EAP 5ではHAシングルトンという機能があり、クラスタ環境下でデプロイメントを一つだけ動かすことができました。クラスタで可用性を担保しつつ、プログラムとしては同時に一つしか動かしたくないというケース(バッチなど)で使用します。
JBoss EAP 6では、このHAシングルトン機能がJava APIの提供に留まっていました(HAシングルトン相当の動きをさせたい場合、処理の続行・ブロック制御を自分で書く)が、EAP7からデプロイのオプションとして復活したようです。
EAP7に同梱されるejb-timerサンプルを使って「クラスタ全体で同時に一つだけ動くタイマー」をデプロイしてみます。
まず既存のejb-timerサンプルをコピーし、HAシングルトンデプロイ用の設定ファイルを配置し、ビルドします。
$ cd path/to/jboss-eap-7.0.0.GA-quickstarts $ cp -R ejb-timer ejb-timer-ha-singleton $ cd ejb-timer-ha-singleton $ mkdir src/main/webapp/META-INF $ echo '<singleton-deployment xmlns="urn:jboss:singleton-deployment:1.0"/>' > src/main/webapp/META-INF/singleton-deployment.xml $ mvn -Dmaven.test.skip=true clean package
次にクラスタ環境を作ります。EAP7をドメイン起動し、ha-singleton-test-server1, ha-singleton-test-server2というサーバを作成します。二つともローカル環境に立てるため、ポートオフセットを指定して各種のポート番号をずらします。
$ cd $JBOSS_HOME/bin $ ./domain.sh & $ ./jboss-cli.sh // ドメイン環境で作成済みのserver-one, server-two, server-threeを停止する。 [domain@localhost:9999 /] :stop-servers // クラスタ対応プロファイル 'ha' のサーバグループ作成 [domain@localhost:9999 /] /server-group=ha-singleton-test:add(profile=ha, socket-binding-group=ha-sockets) // サーバを二つ作成. 二つ目はポートを150ずらす. [domain@localhost:9999 /] /host=master/server-config=ha-singleton-test-server1:add(group=ha-singleton-test, auto-start=false, socket-binding-port-offset=0) [domain@localhost:9999 /] /host=master/server-config=ha-singleton-test-server2:add(group=ha-singleton-test, auto-start=false, socket-binding-port-offset=150) [domain@localhost:9999 /] /server-group=ha-singleton-test:start-servers
先ほどのejb-timerをデプロイします。
[domain@localhost:9999 /] deploy path/to/ejb-timer-ha-singleton/target/jboss-ejb-timer.war --server=groups=ha-singleton-test
このサンプルプログラムは3秒ごとに動くジョブと、6秒ごとに動くジョブで構成されます。下のログを見ると、全てサーバ1で実行されています(ログの左端の部分にノード名が出ています)。
[Server:ha-singleton-test-server1] 18:18:39,002 INFO [stdout] (EJB default - 3) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:18:39 JST
[Server:ha-singleton-test-server1] 18:18:42,002 INFO [stdout] (EJB default - 5) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:18:42 JST
[Server:ha-singleton-test-server1] 18:18:42,003 INFO [stdout] (EJB default - 4) ScheduleExample.doWork() invoked at 2016.07.12 西暦 at 18:18:42 JST
[Server:ha-singleton-test-server1] 18:18:45,006 INFO [stdout] (EJB default - 6) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:18:45 JST
[Server:ha-singleton-test-server1] 18:18:48,002 INFO [stdout] (EJB default - 7) ScheduleExample.doWork() invoked at 2016.07.12 西暦 at 18:18:48 JST
[Server:ha-singleton-test-server1] 18:18:48,003 INFO [stdout] (EJB default - 8) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:18:48 JST
[Server:ha-singleton-test-server1] 18:18:51,006 INFO [stdout] (EJB default - 9) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:18:51 JST
[Server:ha-singleton-test-server1] 18:18:54,002 INFO [stdout] (EJB default - 10) ScheduleExample.doWork() invoked at 2016.07.12 西暦 at 18:18:54 JST
ここでサーバ1を停止します。
[domain@localhost:9990 /] /host=master/server-config=ha-singleton-test-server1:stop
すると、今度は2号機のデプロイメントが活性化し、ジョブが継続します。
[Server:ha-singleton-test-server2] 18:23:30,010 INFO [stdout] (EJB default - 2) ScheduleExample.doWork() invoked at 2016.07.12 西暦 at 18:23:30 JST
[Server:ha-singleton-test-server2] 18:23:30,010 INFO [stdout] (EJB default - 1) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:23:30 JST
[Server:ha-singleton-test-server2] 18:23:33,002 INFO [stdout] (EJB default - 3) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:23:33 JST
[Server:ha-singleton-test-server2] 18:23:36,005 INFO [stdout] (EJB default - 5) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:23:36 JST
[Server:ha-singleton-test-server2] 18:23:36,005 INFO [stdout] (EJB default - 4) ScheduleExample.doWork() invoked at 2016.07.12 西暦 at 18:23:36 JST
[Server:ha-singleton-test-server2] 18:23:39,005 INFO [stdout] (EJB default - 6) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:23:39 JST
[Server:ha-singleton-test-server2] 18:23:42,004 INFO [stdout] (EJB default - 7) ScheduleExample.doWork() invoked at 2016.07.12 西暦 at 18:23:42 JST
[Server:ha-singleton-test-server2] 18:23:42,004 INFO [stdout] (EJB default - 8) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:23:42 JST
ちなみに、HAシングルトンデプロイを有効にする前のejb-timerサンプルをデプロイすると、サーバ1と2の両方でジョブが実行されます。
[Server:ha-singleton-test-server1] 18:27:18,013 INFO [stdout] (EJB default - 1) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:27:18 JST
[Server:ha-singleton-test-server1] 18:27:18,013 INFO [stdout] (EJB default - 2) ScheduleExample.doWork() invoked at 2016.07.12 西暦 at 18:27:18 JST
[Server:ha-singleton-test-server2] 18:27:21,002 INFO [stdout] (EJB default - 5) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:27:21 JST
[Server:ha-singleton-test-server1] 18:27:21,003 INFO [stdout] (EJB default - 3) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:27:21 JST
[Server:ha-singleton-test-server2] 18:27:24,002 INFO [stdout] (EJB default - 6) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:27:24 JST
[Server:ha-singleton-test-server2] 18:27:24,003 INFO [stdout] (EJB default - 10) ScheduleExample.doWork() invoked at 2016.07.12 西暦 at 18:27:24 JST
[Server:ha-singleton-test-server1] 18:27:24,004 INFO [stdout] (EJB default - 4) ScheduleExample.doWork() invoked at 2016.07.12 西暦 at 18:27:24 JST
[Server:ha-singleton-test-server1] 18:27:24,005 INFO [stdout] (EJB default - 5) TimeoutExample.scheduler() EJB timer service timeout at 2016.07.12 西暦 at 18:27:24 JST
Java EE 7でバッチを書けるようになり、HAシングルトンを使う機会も出てくるかもしれません。