WebLogicを動かしているサーバ上で数分間隔にとある機能を動作させたいという話があり、常駐プロセス起動とかにしたくないので、EJBタイマーサービスを使ってみることにしました。
タイマーサービスの使用は初めてなので、WebLogic12Cの挙動を調べながらの作りこみです。
結果的に下記のようになりました。
5分間隔(0分2秒,5分2秒,10分2秒,15分2秒・・・)でタイマー処理を実行しています。
なお、トランザクション処理は必要無し、処理結果のエラーハンドリングも不要、指定の間隔で単純に起動されればよいような機能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
@Singleton public class ChkTimer{ @Schedule(hour="*", minute="*/5", second="2", persistent=false) public void chkProc(){ ExecutorService service = Executors.newSingleThreadExecutor(); service.submit(new Runnable() { @Override public void run() { //ここに処理を書く } } } @Timeout public void ChkTimeout(){ //何もしないけど・・・ } } |
WebLogicにおけるEJBタイマーの挙動として確認できたのは、
①タイムアウトを実装しておかないと30秒以上経つとエラーを吐いて、次のタイマーまでは動くのだが、その次以降はまったく動かなくなる
Caused By: weblogic.transaction.internal.TimedOutException: Transaction timed out after 30 seconds
中略・・
Truncated. see log file for complete stacktrace
なぜ30秒なのかというとトランザクションタイムアウト値がそうなっているっぽい。。
https://docs.oracle.com/cd/E28613_01/web.1211/b65951/ejb_jar_ref.htm#i1506703
何をするわけでもないが、とりあえず@Timeoutのアノテーションをつけたメソッドを追加
②処理時間が次回のタイマー処理開始を超えるとタイマーが止まる
例えば、5分間隔で動作させる場合、処理が5分以上掛かってしまうと、次のタイマー実行時にエラーが吐かれて動かない
<2016/11/15 16時55分07秒 JST> <Error> <EJB> <BEA-011088> <The following error occurred while invoking the ejbTimeout(javax.ejb.Timer) method of EJB ChkTimer(Application: appmgr, EJBComponent: /appmgr).
以下、略・・
なので、処理自体をExecutorServiceでスレッド処理にし、処理遅延が起きないようにしてみました
③永続化はしない方がよい
とりあえずサーバ上で空回りするようタイマー稼動テストを数日間したところ、ちゃんと指定間隔通りに動作していたので、機能を概ね実装していざデプロイしてみると、2重起動している状態に、、
なぜかといろいろ調べた結果、空回り開始時にpersistent=falseを指定していなかったので、ずっと残り続けていた模様。
一度、タイマー起動を無しにしたモジュールでデプロイした後、再度タイマーを有効にしてデプロイすることで、やっと2重起動が止まりました。
実行したいスケジュールや処理内容によっては、結構制御が難しいように思いますが、今回の要件ならOKという事で。