Tomcat 6.0.35 サーバーの 2 つのアプリで、「どこからともなく」メモリ リークが発生しました。1 つのアプリは Solr で、もう 1 つは独自のソフトウェアです。過去数週間私に起こっていたので、誰かがこれを以前に見たことがあることを願っています.Tomcatを本番環境で再起動し続ける必要があります.
スレッドまたは DB 接続操作に関連するコードはまったく変更されていないにもかかわらず、元のサーバーに表示されました。このアプリが実行されている古いサーバーは廃止される予定だったので、古いものを一掃するという考えで、サイトを新しいサーバーと「よりクリーンな」環境に移行しました。しかし、それは起こり続けています。
Tomcat がシャットダウンする直前に、catalina.out ログに次のようなエラーが記録されます。
2012-04-25 21:46:00,300 [main] エラー org.apache.catalina.loader.WebappClassLoader- Web アプリケーション [/AppName] は [MultiThreadedHttpConnectionManager cleanup] という名前のスレッドを開始したようですが、停止に失敗しました。これにより、メモリ リークが発生する可能性が非常に高くなります。
2012-04-25 21:46:00,339 [main] エラー org.apache.catalina.loader.WebappClassLoader- Web アプリケーション [/AppName] は、[com.mchan ge.v2.async.ThreadPoolAsynchronousRunner$ という名前のスレッドを開始したようです。 PoolThread-#2] ですが、停止に失敗しました。これにより、メモリ リークが発生する可能性が非常に高くなります。
2012-04-25 21:46:00,470 [main] エラー org.apache.catalina.loader.WebappClassLoader - Web アプリケーション [/AppName] はまだ完了していない要求を処理しています。これにより、メモリ リークが発生する可能性が非常に高くなります。標準の Context 実装の unloadDelay 属性を使用して、リクエストが終了するまでの時間を制御できます。
その移行中に、問題を修正するために Solr 1.4 から Solr 3.6 に移行しました。上記のエラーがログを埋め始めると、以下の Solr エラーが 10 ~ 15 回繰り返された直後に続き、Tomcat が動作を停止し、応答するにはシャットダウンして起動する必要があります。
2012-04-25 21:46:00,527 [main] エラー org.apache.catalina.loader.WebappClassLoader - Web アプリケーション [/solr] は、タイプ [org.a pache.solr.schema.DateField. ThreadLocalDateFormat] (値 [org.apache.solr.schema.DateField$ThreadLocalDateFormat@1f1e90ac]) およびタイプ [org.apache.solr. schema.DateField.ISO8601CanonicalDateFormat] (値 [org.apache.solr.schema.DateField$ISO8601CanonicalDateFormat@6b2ed43a]) ですが、Web アプリケーションが停止したときに削除できませんでした。これにより、メモリ リークが発生する可能性が非常に高くなります。
私の調査では、スレッドを管理するコードを変更して、DB プール接続などを強制終了するようにすることについて多くの提案がありましたが、このコードは 12 か月近く変更されていません。また、Solrアプリケーションがクラッシュしています。これはサードパーティであるため、これは環境的なものであると考えています(jarの競合、バージョン管理、構成のファットフィンガー?)
私の最後の変更は、Java 用の mysql コネクタを最新のものに更新することでした。以前のリリースでは、プールに関するメモリ リークのバグがいくつか存在していましたが、サーバーはわずか数時間後に再びクラッシュしました。
私が気付いたことの 1 つは、Tomcat Web マネージャーで何千ものセッションが表示されていることですが、それはニシンである可能性があります。
誰かがこれを見たことがあれば、どんな助けでも大歓迎です。
[編集]
問題の原因を見つけたと思います。結局、メモリリークではありませんでした。私は、Hibernate を介したデータベース プーリングにc3p0を使用する別の開発チームからアプリケーションを引き継ぎました。c3p0 にはバグ/機能があり、DB 接続を解放しないと、すべての接続 (MaxPoolSize 経由: デフォルトは 15) が使用されると c3p0 が待機状態になる可能性があります。接続が利用可能になるまで無期限に待機します。したがって、私の失速。
最初に MaxPoolSize を 25 から 100 に上げたところ、アプリケーションはハングすることなく数日間実行され、その後 100 から 1000 に変更され、それ以来 (2 週間以上) 安定して実行されています。
プールされた接続が不足している理由を調べる必要があるため、これは完全な解決策ではありません。そのため、c3p0 の unreturnedConnectionTimeout を 4 時間に設定し、アクティブかどうかに関係なく、すべての接続に 4 時間の時間制限を適用します。アクティブな接続の場合は、接続を閉じてから再度開きます。
きれいではなく、c3p0 は推奨していませんが、問題の原因を突き止めるための息抜きのスペースを与えてくれます。
注: Hibernate で c3p0 を使用する場合、設定は persistence.xml ファイルに保存されますが、すべての設定をそこに置くことはできません。一部の設定 (unreturnedConnectionTimeout など) は、c3p0.propertiesに入れる必要があります。