• ベストアンサー

コネクションプーリングの枯渇

tomcat-Servletでの開発を行っています。 MVCモデルでのWEBアプリケーションです。 DBへの接続用として自作のコネクションプーリングを使用しています。 (プーリング数は20を設定) 基本的なSQL実行フローは下記のようになります。 1.コネクションプーリングを取得 2.SQL文を実行 3.コネクションプーリングを返却 ところが、時間を置いて psコマンドで確認すると、 だんだん数が減っていっているようです。 原因を調査しているのですが、 もし次のような原因で正しいかどうか分かりましたらご連絡ください。 <考えている原因> 要するに上記の3(返却)がされていないのであって。 ・実行処理中に利用者がクライアント側のブラウザを落としている。 と仮説を立てているのですが。 この仮説が正しいかどうか、 また、もし正しい場合には、どうすれば回避可能かをご教授ください。 補足の必要があればご連絡ください。 (コネクションプーリングの全文を載せたいのですが、  長すぎるようで・・・)

  • ssm3u
  • お礼率70% (42/60)
  • Java
  • 回答数4
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • hidebu-
  • ベストアンサー率53% (45/84)
回答No.3

仮説に関してはログ状況をみれば判明すると思います。 単純にロジックで返却しわすれているところがあったりするかもしれません。 (とくに外注を多く使っている場合はよくあります) ブラウザ側で途中終了した場合でもサーバー側のスレッドは流れているはずなので、単純な業務ロジックのミスだと考えるのが妥当だと思いますが。 時間がなければ、コネクションマネージャーを作成して、コネクションの状況を監視させて強制的にプールに返却するのもいいかもしれませんね。 (これは以前にやった記憶があります)

ssm3u
質問者

補足

ありがとうございます。 私のほうでも返却忘れではないかと調査しましたが、 どうやらそうではないようです。 全てのソースを確認し返却忘れがないことを確認しました。 > ブラウザ側で途中終了した場合でもサーバー側のスレッドは流れているはず このあたりについて少々詳しくお教え頂ければと思います。 コネクションマネージャについては、 これから調べてみます。

その他の回答 (3)

  • hidebu-
  • ベストアンサー率53% (45/84)
回答No.4

実験してみればわかるとおもいますが broken pipeになっても1リクエストに対して対応する1スレッドは異常がない限り流れます。 1分間スリープで止めた後に何かしら処理をするロジックをかいてみると、リクエストをしたあとに即ブラウザを落としても、処理が続行されているのが確認できます。 ですから、業務ロジックでの例外処理等のミスで返却処理が省略されてしまっていると考えるのが一番妥当なのです。 そして、結合テスト以降のフェーズになるとロギングの粒度の細かさで原因追求の精度がきまってきます。 業務ロジックのほうにロギング処理をいれるのがきついのであれば、プールのほうでコネクション取得時にIDを付与し(ハッシュコードでよいでしょう)時刻と取得した旨をログ出力 返却されたときに同じようにログ出力をしてみて、使用状況を把握できるようにしておくのがよいかと。 コネクションマネージャは単に取り出された時刻を記憶しておき、正常処理時にはありえない時間が経過しても返却されていなければ強制的にプールに返却するようにするだけです。

ssm3u
質問者

お礼

お返事おそくなりましたことお詫びします。 ブラウザを落としても、 処理が続行されていることが確認できました。 業務ロジックの見直し作業も終了しましたので、 あとはログ情報から少々様子を見て今後の対応を計ります。 いろいろとありがとうございました。

ssm3u
質問者

補足

補足遅れましたことお詫び致します。 上記「スレッド」というのは、 いわゆるRunnable実装のスレッド(Thread)を使用して DBの検索や更新を行うということでしょうか? あるいは、 もしサーブレットのみのプログラムであった場合でも、 リクエスト中にブラウザを落としても、 処理は最後まで実行されるということでしょうか? (Responseだけがない状態。) 現在自作のプーリングを使っているのですが、 オライリー「Javaサーブレットプログラミング」(くま本) を買ってきました。 この中にプーリングサンプルがあったので、 こちらを勉強してみたいと思います。 ありがとうございます。

  • davosuke
  • ベストアンサー率61% (34/55)
回答No.2

>以下の点、ついでにお伺いしたいと思います。 >・結局のところ上記の仮説は正しいのでしょうか? システム全体が見えないので、なんともいえませんが 確かに上記の仮説も正しいと思いますが、それだけではないかもしれません。それが何といわれれば、わかりかねますが、トラフィックをかけ高負荷状態のテストしてたら 何かわかるかもしれません。 >・EJB(?)、J2EE、JNDI、各APサーバなどのプーリング>機能を使うと、枯渇するといったことは無くなるの >でしょうか 前に携わったシステム開発で軽減しました。 AP側の問題もあるかもしれませんので 確実ではありませんが・・・・・・・・ 以上、補足回答します

ssm3u
質問者

お礼

ありがとうございました。 とりあえず今回は、 全体のSQL文を見直し、処理速度を上げることで、 「ブラウザ終了」のされにくいシステムにしようと思います。 (現状「待ちきれない」ところに原因があるのではないかと・・・) JNDIとしても導入に時間がかかるため、 こちらは今後順次対応していきたいと思います。 ありがとうございました。

  • davosuke
  • ベストアンサー率61% (34/55)
回答No.1

EJBのプール機能を使ってみてはどうですが、 貴方様の開発の現状からST(システムテスト)等のフェーズなのでいまさらEJBの導入するのはどうかと思いましたが、アドバイス程度でお願いします。 メリット (1)EJBのプール機能を使いDBサーバの負荷を軽減させる。 (2)サーブレットとDB巻のフィルタに役割を担う デメリット (1)EJBに対してある程度の設計製造期間が必要

参考URL:
http://java-house.jp/ml/archive/j-h-b/050079.html#body
ssm3u
質問者

補足

さっそくの回答ありがとうございます。 確かに自作のところに問題があるのかもしれません。 以下の点、ついでにお伺いしたいと思います。 ・結局のところ上記の仮説は正しいのでしょうか? ・EJB(?)、J2EE、JNDI、各APサーバなどのプーリング機能を使うと、  枯渇するといったことは無くなるのでしょうか?

関連するQ&A

  • DBCPで、DB切断後のコネクション取得

    struts1.3 + spring1.2 + tomcat + oracleで開発中です。 DBCPでコネクションがプーリングされた状態で、DBが停止・再起動 した場合、DB停止前からプーリングされていたコネクションは 無効になってしまいますが、これの対処はどうするのがベストでしょうか。 (1) testOnBorrow で検査する →コネクション取得の都度発行される検査用SQLの負荷が心配 (2) testWhileIdle で検査する。 →検査スレッドの起動間隔はどれくらいが適当なのか? (3) getConnection時に自前でリトライするロジックを組み込む →WebSphereにある、StaleConnectionExceptionのような例外がある? (4) もっと別の画期的な方法がある!! 以上、よろしくお願いします。

  • コネクションプーリングの確認方法について

    JDBCを使用してOracleへアクセスするWeb画面があります。 コネクションプーリングに対応しているとのことなので、実際に有効になっているのか確認したいのですが、次の方法で正しいのでしょうか。 (1)SQL文が実行されるWeb画面の処理を動作させた時に、OracleのV$SESSIONで、存在する「セッション識別子+シリアル番号」を確認する。 (2)この処理を何回実行しても、V$SESSIONに同じ「セッション識別子+シリアル番号」の行が存在したままになるのか確認する。 もし、Web画面の処理を実行させる度に、新しい「セッション識別子+シリアル番号」の行が増えていく場合は、コネクションプーリングが有効になっていないと考えてもいいのでしょうか。 現状は、コネクション上限数の設定に関係なく、V$SESSIONに新しい行がどんどん発生し、古い行はあるタイミングでごっそり消えるという状態です。これはコネクションプーリングされている状態なのか、コネクションプーリングされていない状態なのか、それともコネクションプーリングとは全く関係ないのか知りたいです。 (なお、アイドルタイムアウトの設定は十分長く、タイムアウトは発生しない(はず?)のタイミングでWeb画面を操作しています。)

  • Tomcat6のコネクションプーリングについて

    Tomcat6のコネクションプーリングについて 現在、以下の環境で開発を行っているのですが、 データソースからConnectionを取得できていない状況です。 過去に同様の内容が記載されていたのですが、 内容が理解できず投稿させていただいております。 【フォルダ構成】 test  |  |--META-INF  |   |  |   --context.xml  |  |--WEB-INF     |      --web.xml 【環境】 Windows XP Pro Eclipse3.3.2 apache2.2 tomcat6.0 jdk1.6.0_18 mysql-connector-java-5.1.12-bin.jar Struts2 以下に、context.xml、web.xml及び、サーブレットのコードを記載します ■web.xml=========== <?xml version="1.0" encoding="UTF-8"?> ~~(抜粋)~~ <resource-ref> <res-ref-name>test</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </web-app> ■context.xml======= <?xml version="1.0" encoding="UTF-8"?> <Context displayName="test" docBase="test" path="/test" reloadable="false"> <Resource name="jdbc/test" auth="Container" type="javax.sql.DataSource" username="root" password="root" driverClassName="org.gjt.mm.mysql.Driver" url="jdbc:mysql://localhost/test?useUnicode=true&amp;characterEncoding=UTF-8" maxActive="4" maxWait="5000" maxIdle="2" validationQuery="select cont(*) from db_fuzoku" /> </Context> ■サーブレットコード(抜粋)===== public class test_Dao { DataSource ds; public ArrayList select(){ ArrayList list = new ArrayList(); try { // 初期コンテキストを取得 Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); // ルックアップしてデータソースを取得 ds = (DataSource) envCtx.lookup("jdbc/test"); } catch (Exception e) { e.printStackTrace(); } Connection con = null; Statement stmt = null; try { // データソースからConnectionを取得 con = ds.getConnection(); ==================== 以上、よろしくお願いします。

  • コネクションプールについて

    コネクションプール有とコネクションプール無でDB接続・切断を繰り返したときに どれくらい差があるか試してみようと思いWebアプリ上(フレームワークにStruts2を使用)で 下記コードを実行してみました。 dbcpConnectメソッド(コネクションプール有) と jdbcConnectメソッド(コネクションプール無) をそれぞれ千回づつループで回して実行してみました。 結果は 【コネクションプール有】実行にかかった時間:157384 ミリ秒 【コネクションプール無】実行にかかった時間:158760 ミリ秒 で大差はありませんでした。 コネクションプールを使用するともう少し早いと思っていたのですがそのようなことはないのでしょうか。 public String test4() { // コネクションプール有の接続 long start = System.currentTimeMillis(); for(int i=0; i< 1000; i++) { dbcpConnect(); } long stop = System.currentTimeMillis(); System.out.println("実行にかかった時間は " + (stop - start) + " ミリ秒です。"); // コネクションプール無の接続 start = System.currentTimeMillis(); for(int i=0; i< 1000; i++) { jdbcConnect(); } stop = System.currentTimeMillis(); System.out.println("実行にかかった時間は " + (stop - start) + " ミリ秒です。"); return "jstl4"; } public void dbcpConnect() { Connection con = null; try{ Context context = new InitialContext(); //DataSource ds = (DataSource)context.lookup("java:comp/env/jdbc/library"); DataSource ds = (DataSource)context.lookup("java:/comp/env/jdbc/dhcpTest"); con = ds.getConnection(); Statement stmt = con.createStatement(); String sql = "SELECT * FROM test.test"; ResultSet rs = stmt.executeQuery(sql); } catch(Exception e) { System.out.println("Error"); } finally { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } public void jdbcConnect() { Connection con = null; try{ con = DriverManager.getConnection("jdbc:mysql://localhost", "root", "root"); Statement stmt = con.createStatement(); String sql = "SELECT * FROM test.test"; ResultSet rs = stmt.executeQuery(sql); } catch(Exception e) { System.out.println("Error"); } finally { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } }

    • ベストアンサー
    • Java
  • サーブレットで使用しているBeanを通常のJavaプログラムで再利用したい

    サーブレットで使用しているBeanを通常のJavaプログラムで再利用したいと考えています。 通常のJavaプログラムというのは サーバにtelnetログインし javaコマンドで実行するプログラムを指します。 サーブレット側では、 JDBCを利用したコネクションプーリング(JavaBean)を使用しています。 通常のJavaプログラムでも、このBeanをimportして使用したいのですが、 実行時エラーとして、 Exception in thread "main" Backend start-up failed:FATAL: Sorry, too many clients already とエラー表示されます。 DBは postgres を使用しています。 使用するために必要な設定等わかりましたら教えてください。 コネクションプーリング(JavaBean)全文を記載したかったのですが、 字数制限に引っかかりましたので省略します。 必要あれば補足に記載します。

    • ベストアンサー
    • Java
  • JSP-Servlet-JavaBeansを使った場合のデータベースアクセスについて

    JSP-Servlet-JavaBeansで開発するときに、 業務ロジックはModelであるJavaBeansの中で作成すると 思います。 様々なサンプルを見ると、そのJavaBeansの中で データベースへのコネクションを作成し、SQL文を実行して 値を取得しています。(DBへの接続文字列や接続ユーザ、パスワード等も固定になっています) しかし、DBへの接続文字列(特にサーバ名)や 接続ユーザ・パスワードなどは、普通Servlet初期パラメータから取得して設定するべきだと思います。 Servletだけで開発しているときは、 DBManagerのようなクラスを作成し、コンストラクタの引数に接続文字列等を渡していたのですが、 JavaBeansの場合はどうなるのでしょう? (同じように引数付きのコンストラクタを作成するのでしょうか??) また、今まではServletのini()で使ってコネクションをプール実現していたのですが、JSP-Servlet-JavaBeansを使うと、どのように処理を分ければよいのでしょうか? 長文で大変申し訳ありませんが、ぜひ良きアドバイスを お願いします。

    • ベストアンサー
    • Java
  • java log4jの環境設定

    調べてみたのですが、参考になるページが見当たらなかったので(私が理解できなかっただけかもしれませんが。。) ご質問させていただきます。 表題の件です。javaのサーブレットを用いてログ出力する為にlog4jを使用しています。 そのため、log4j.xmlにファイルの出力先やらなんやらを記述しています。(これが通常だと思います) tomcatのWEBアプリケーションパッケージですので、DB接続等の設定は「META-INF/context.xml」に記述(Javaアプリ側で名前解決してDatasourceとして取得)しています。 上記からDB接続情報、ログの出力先情報はそれぞれ別ファイル(XML)から取得していますが、環境依存する値なので、編集するならひとつのファイルから行いたいです。 できれば、log4jのファイル出力先情報等をcontext.xmlにて記述して解決したいです。 (理由:tomcat6/servlet2.5を使用しており、tomcat6のdbcpを使用してコネクションプーリングしている為、DB接続の方法は変更したくない為) 以上、ご存知の方ご教授お願いできますでしょうか。

    • ベストアンサー
    • Java
  • JAVA ServletでSQL Serverに接続できないんですが。

    マイクロソフトのサイト(SQL SERVER2000 Driver for JDBC)から ドライバーを取ってきて、JAVAからDB接続テストを行っています。 最初に簡単なJAVAアプリを作って実行したところ、うまく動作しました。その後、Servletで同様のtestをしたところ、Tomcatのコンソール画面に、ClassNotFoundExceptionが出て、実行できません。 下記の命令が、処理できないようです。 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); CLASSPATHの設定もコマンドプロンプトで、setコマンド実行結果で確認済みです。 他のデータベース(MySQL)では、Servlet,JSP,JAVAアプリすべて、うまく実行できました。 ご存知の方、よろしくお願いいたします。 環境:(1台のマシン内での仮想ネットワーク) windows XP Pro (SP1) j2SDK 1.4.1_03 Tomcat4.1 SQL Server2000

  • コネクションプーリングについて

    WebアプリケーションとRDBMSの接続時間の軽減として、 コネクションプーリングという手段があるそうです。 ただ、実装に手間がかかるそうです。 アプリケーションサーバーはこれを実装しているようですが、 そんな予算はありません。 そこで、この部分をやってくれるオススメなソフトなぞはあるでしょうか? ちょっと調べたところ「jdbshare」、「PoolMan」などがありましたが。 もしかして、Tomcat自体にコネクションプーリングの機能があるのでしょうか? なにぶん勉強不足で申し訳ありませんが、よろしくお願いします。

    • ベストアンサー
    • Java
  • BLOB型の画像データを表示したい

    環境 OS   : WindowsXP JDK  : 1.5.0_11 Apache : 2.2.4 Tomcat : 5.5.9 eclipse: 3.3.0 struts : 1.2.7 MySQL : 5.0 DBにBlob型として格納した画像データを、 Servlet/JSPでSELECT文を実行して、結果をブラウザに表示する方法が知りたいです。 間違っていたら申し訳ないのですが imgタグからServletを呼び出しその中で処理を行うと 聞きました。 どのような記述をするのでしょうか。 またDBへの接続、SELECT文の実行は分かるのですが その後、どのようにして表示するのでしょうか。 サンプルコードなどありましたら、教えていただきたいと思います。 宜しくお願いします。

    • ベストアンサー
    • Java

専門家に質問してみよう