
ほぼ同等のハードウェア構成 (両方とも RAM が 24 GB 以上) を持つ 2 つの異なるサーバー (Oracle jdk7) に、2 つの異なる Tomcat 7 インスタンスがあります。両方の Tomcat サーバーは同じ構成で、同じ Web アプリケーションがこれらのサーバーにデプロイされています。catalina のオプションは次のとおりです。
-XX:PermSize=128m -XX:MaxPermSize=512M -Xmx2048m -XX:+CMSIncrementalMode -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC
負荷テスト (大量の並列実行リクエストで REST API に負荷をかける) の実行中に、サーバーの 1 つがスローされますjava.lang.OutOfMemoryError: Java heap space
(スタック トレースは次のとおりです。http://pastebin.com/wuS1MVCC)、他のサーバーは正常に動作します。なぜこのようなことが起こるのか全く分かりません。同様の問題に遭遇した方はいらっしゃいますか?
答え1
つまり、Tomcat JVM の 1 つが、割り当てられた 2048 MB のヒープを超えようとしているということです。
試すべきことのチェックリストと同じくらい具体的な答えを探しているようですので、ここに示します。
ヒープ不足は、メモリ リーク (リクエストごとに少しずつリークする) が原因である可能性があります。または、負荷シナリオでは、JVM が処理できる以上の負荷を JVM に投入していることが原因である可能性があります。どちらが問題なのかを特定する必要があるため、まずは負荷を生成する方法を確認します。
問題が高レベルの並列リクエストでのみ発生し、低レベルの並列リクエストでは発生しない場合は、リクエスト数と各リクエストの処理に必要なメモリの積が大きすぎるという問題があります。各リクエストで使用するメモリを減らすか、何らかの方法で同時実行を制限する必要があります。
同時実行性に関係なく、一定数のリクエストが処理された後に問題が発生する場合は、メモリ リークが発生しています。メモリ リークを見つけて、メモリを再利用する必要があります。
どちらのシナリオでも、優れたヒープ メモリ アナライザーがあれば大いに役立ちます。YourKit Java Profiler のような優れた市販のアナライザーや、Eclipse Memory Analyzer のような無料のアナライザーがあります。自分に合ったツールを見つけて、その使い方を学んで、メモリを消費しているものを調べてください。プログラムを起動するために必ずしもツールを使用する必要はありません。サーバー上で負荷テストを実行している場合は、JDK の jmap コマンドライン ツールを使用してファイルにヒープ ダンプをキャプチャし、そのダンプ ファイルを分析するためにツールを使用できます。このツールは、ヒープ内でどのオブジェクトがスペースを消費しているかを表示します。
答え2
がある何か2 つのシステム間で異なる場合、動作に違いはありません。GC に時間がかかりすぎて結果が少なすぎる場合も、エラーが発生する可能性があることに注意してください。ヒープの制限近くで実行すると、GC でこの種の問題が発生します。
過剰な GC 時間と OutOfMemoryError
同時実行コレクターは、ガベージ コレクションに時間がかかりすぎると、OutOfMemoryError をスローします。ガベージ コレクションに合計時間の 98% 以上が費やされ、ヒープの 2% 未満が回復された場合、OutOfMemoryError がスローされます。この機能は、ヒープが小さすぎるためにアプリケーションが長時間実行されてもほとんどまたはまったく進行しない状態を防ぐように設計されています。必要に応じて、コマンド ラインにオプション -XX:-UseGCOverheadLimit を追加して、この機能を無効にすることができます。