2012-07-11 20 views
21

Tomcat(7.0.28)を実行しているJava Webアプリケーションが定期的に応答しなくなります。私は可能性のある犯人(同期?)のいくつかの提案だけでなく、クラッシュ時に何が起こっているかについての詳細情報を収集するためのいくつかの推奨ツールを期待しています。私が蓄積してきたいくつかの事実:TomcatのJava Webアプリケーションが定期的にフリーズする

  • ウェブアプリがフリーズすると、Tomcatはアプリにリクエストスレッドを供給し続けますが、アプリはそれらを解放しません。スレッドプールは最大値(現在は250)まで満たされ、その後の要求は直ちに失敗します。通常の操作では、アクティブなスレッドは2〜3つしかありません。

  • 問題が発生したときに、TomcatまたはWebアプリケーションのログに記録されているエラーや例外はありません。

  • tomcat管理Webアプリケーションを使用してアプリケーションで「停止」をクリックして「開始」を行うと、すぐにこの問題が解決されます(今日まで)。

  • 最近の頻度は1日2〜3回でしたが、今日はさらに悪化しましたが、おそらく20回、すぐには生活に戻ってこない場合もあります。 、サーバー上のプロセッサとメモリ使用量がフラット(とかなり低い)のまま

    問題は私たちの病期分類システムに問題が発生した

  • では発生しません

  • 問題は、営業時間中にのみ発生します。 Tomcatはたくさんの空きメモリを報告します。

  • 問題が発生した場合、Tomcatは引き続き応答します。管理Webアプリケーションはうまく動作し、プール内のすべてのスレッドがいっぱいになるまでTomcatはリクエストをアプリケーションに送信し続けます。

  • 私たちのデータベースサーバーは、問題が発生しても応答し続けます。データアクセスと注入にSpringフレームワークを使用します。

  • 問題は一般的に使用量が多い場合に発生しますが、使用頻度が異常に高いスパイクはありません。

  • 問題の履歴:約1年半前に同様のことが発生しました。多くのサーバー設定とコードの変更後、問題は約1カ月前まで消えてしまいました。過去数週間の間に、それはずっと頻繁に発生し、平均して1日に2〜3回、場合によっては数回連続して発生した。

  • 今日はスレッドセーフではないサーバーコードがいくつか確認されていますが、そのために修正が加えられましたが、問題はまだ発生していません(あまり頻繁ではありません)。これは、スレッドセーフではないコードが引き起こす可能性のある問題ですか?

UPDATE:データベース接続プールの枯渇を示唆し、いくつかの記事では、私はその方向にいくつかの検索を行なったし、ほとんどすべて私が経験してるの問題を説明し、この他のStackoverflow questionを見つけました。

ApacheのBasicDataSource実装でのmaxActive接続とmaxIdle接続のデフォルト値はそれぞれ8です。maxWaitは-1に設定されているため、プールが使い果たされ、新しい接続要求が到着すると、どんな種類の例外も記録することなく永遠に私はまだこの問題が再び起こるのを待つつもりで、JVM上でjstackダンプを実行して、その情報を分析できるようにしますが、これは問題のようです。それが説明していない唯一の理由は、アプリがこの問題から回復しないことがある理由です。私は要求がたまに積み重なると思うし、一度それが後になると追いつくことはできません。

UPDATE II:私はクラッシュ時のjstackを実行し、以下の約250(最大スレッド)が見つかりました:

"http-nio-443-exec-294" daemon prio=10 tid=0x00002aaabd4ed800 nid=0x5a5d in Object.wait() [0x00000000579e2000] 
    java.lang.Thread.State: WAITING (on object monitor) 
     at java.lang.Object.wait(Native Method) 
     at java.lang.Object.wait(Object.java:485) 
     at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1118) 
     - locked <0x0000000743116b30> (a org.apache.commons.pool.impl.GenericObjectPool$Latch) 
     at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106) 
     at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044) 
     at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) 
     at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) 
     at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:573) 
     at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:637) 
     at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:666) 
     at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:674) 
     at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:718) 

私の素人目には、これはかなり決定的に見えます。データベース接続プールが上限に達したようです。私はmaxActiveとmaxIdleを変更せずにmaxWaitを3秒に設定して、プールが満杯になったときに例外が記録されることを確認しています。これらの値を適切なものに設定して監視します。 10.へ

org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object 
     at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:114) 
     at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044) 
     at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) 
     at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) 

私が-1(無限)MAXACTIVEを設定したとmaxIdle私はします:

UPDATE III:予想通りMAXWAITを設定した後、私は、私のログにこれらを見始めましたしばらく監視していますが、私の推測ではこれが問題の終わりです。

+7

'kill -3 'はあなたの友人です。これを実行し、スレッドダンプを見てください。情報のグループ化(http://java.net/projects/tda/)のために、スレッドダンプアナライザを見たいと思うかもしれません。 – mindas

+0

他の情報なしで野生の推測(スレッドダンプが必要です!):DB接続プールが枯渇しました。 –

+1

これはまさに私に起こっていたことです。ウェブアプリケーションが大きくなりすぎました。最大接続が低すぎるし、待ち時間がうまくいかず、スレッドがまったく積み重なってしまい、サーバーがフリーズしてしまいました。最大の短所を増やし、特定の時間を最大待ち時間に設定しました。今は監視していますが、サーバーは正常に動作しています。このミニチュートリアルをありがとう。 – Lauro182

答えて

12

経験から、データベース接続プールの実装を確認することをお勧めします。データベースには十分な容量がありますが、アプリケーション内の接続プールは少数の接続に制限されている可能性があります。詳細は覚えていませんが、同様の問題があることを思い出してしまいました。これは、BoneCPを使用して切り替えた理由の1つで、負荷テストで非常に高速で信頼性が高いことがわかりました。

以下に示すデバッグを試した後、プール内で使用可能な接続数を増やして、影響があるかどうか確認してください。

私はスレッドセーフではなかったかもしれない、今日、いくつかのサーバーコードを識別し、 と私はそのために修正を入れたが、問題はまだ(ただし、あまり頻繁に) が起きています。これは、 スレッドセーフでないコードによって引き起こされる問題のようなものですか?

これはスレッドセーフであるかどうかによって異なります。あなたのアプリケーションがスレッドをdeadlockにしているかのように私には聞こえます。デバッガを接続し、JVisualVM、JConsole、または他のプロファイリングツール(YourKitは優れたIMO)を使用するように設定されたJVMを使用して、実動環境を実行して、どのスレッドを持っているかを調べることができます。待っている

+0

はいBoneCPの岩です。 commons-dbcpは吸う。 Tomcat 7はdbcp https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.htmlに同梱されていますが、ドライバを使用するにはtomcat-jdbc.jarと同じクラスローダからアクセス可能でなければなりません新しいtomcatをインストールするたびにtomcatのlibディレクトリにドライバのjarファイルを置くことを気にしたくありません。 – redochka

+0

Redsonic:そうではありません。 'DataSource'がコンテキスト内で定義され、コンテキスト間で共有されるJNDIリソースではなく、コンテキストのクラスパス(つまり.war)に存在することができます。これは私が運用システムでどのように使用したかです。 –

+0

ah ok。私は自分自身をテストしなかった。私はtomcat 7の文書にあったものを報告しました。さて、この場合、それはオプションです:) – redochka

関連する問題