S2JDBCでJNDI経由でDataSourceを取得すると止まってしまう

久々にSAStrutsネタ、というかS2JTA、S2JDBCネタか?

な環境。Tomcatがかなり古いのは気にしない。

発端はJDBCの設定をS2のダイコンではなく、Tomactのコンテキスト記述子に書こうとした事。こちらのエントリの設定を参考にして、JNDI経由でDataSourceを取得し、DataSourceXADataSourceクラスを使う事でDB接続は成功。しかしCool DeployのときにApache Benchで負荷をかけるとレスポンスが帰ってこなくなってしまう。Hot Deployでは問題ないのに…。

ログを見ると以下の行を最後に止まっている。DBアクセス時に停止しているのでDBがらみの問題かと思われる。

DEBUG [http-8080-Processor24] (org.seasar.extension.jdbc.query.AutoSelectImpl) select T1_.ID as C1_ ...

設定ファイルを眺めていて、Tomcat側のコネクションプーリングとSeasar2のコネクションプーリングがダブっているのが良くないのでは?と考えた。

設定を見ると、Tomcatのコンテキスト記述子に書かれているデータソース設定のmaxActiveが5、Seasar2のjdbc.diconのmaxPoolSizeが10となっている。SAStrutsが6つめのコネクションを取りに行くとき、Tomcat側にプールされている接続は全てSeasar2にプーリングされ使用中となっているので、Seasar2がプーリングを破棄するまで接続が取得できなくなってしまうのだろうと推測した。

推測の根拠はログを見ると「物理的なコネクションを取得」というのが5回までは出ることだ。また、Hot Deployで問題ないのは、リクエストごとにクラスローダが破棄されるのでプーリングも破棄されてしまうのだろう。

推測が正しければ、TomcatのプールサイズをSeasar2より大きくすれば発生しないはずだ。S2側のmaxPoolSizeを3に減らしてしてApache Benchを実行してみる。止まらない。次に、S2のmaxPoolSizeを10に戻し、TomcatのmaxActiveを11に変更。条件を変えて何度か試してみたところが止まることはなかった。これで人類の勝利か?

ダメ押しにTomcatのmaxActiveを5に戻し、S2のmaxPoolSizeを0にしてSeasar2側のプーリングを無効にした。しかし、6つめのコネクションを取りにいくときに停止してしまう…。あるぇ〜?

推測が外れているのか、maxPoolSizeを0にしてもプーリングしないというわけではないのか?もうこの辺で時間切れになったのでJNDIでDataSourceを取得するのはやめて、無難にjdbc.diconにJDBCの設定を記述する事にした。DataSourceXADataSourceの素性をよく調べてみないとダメそうな気がする。あとはConnectionPoolImpl辺りか…。冬休みの宿題かなあ…

ま、本来JNDIからデータソースを取得するのはJTAを実装しているJ2EEサーバ向けの機能でTomcatで使うようなモノじゃないのだろう。JOTMを使ってTomcatにJTAを組み込んでしまうとか、JNDIに直接MySQLのXADataSource実装クラスを設定してしまうとか、いっそGlassFishかJBOSSを使うとか、回避方法はいくつかあるだろう。そもそもこの程度のアプリに分散トランザクションなんかいるの?という疑問もあるのだがアノテーション使ってトランザクション境界を設定できるのは便利だからな〜