サーブレットの仕様では、メモリに関する考慮事項については何も述べられていないため、何の助けにもなりません。
特にそうしないように構成されていない限り、Tomcat は HttpSession オブジェクト (実際にはそのコンテンツ) で利用可能なすべてのメモリを使い果たすことを許可し、最終的に JVM はOutOfMemoryError
s をスローし始め、サーバーをダウンさせる可能性があります (ただし、JVM は引き続き実行されます) 、多くのことが動作します...予期せず、残念なことに)。
単一のリクエストがローカル変数などで大量のメモリを使用し始めると、リクエストを処理するスレッドが影響を受けOutOfMemoryError
、現在のリクエストの処理を停止します。(この場合、リクエスト処理スレッドはTomcatリクエスト処理スレッドプールによって実際にリサイクルされると思います)。その後すぐにガベージ コレクタが実行され、そのリクエストで使用されたメモリが再利用され、サーバーが安定します。
一方、大量のメモリを使い果たし、それらのオブジェクトをユーザーの に格納するとHttpSession
、GC はメモリを解放できず、サーバーは継続的にOutOfMemoryError
s に悩まされます。Tomcat は指定されたスケジュールでセッションを期限切れにしますが (デフォルトでは非アクティブ状態が 30 分間続く)、セッション クレンジング スレッドはOutOfMemoryError
during 操作に遭遇する可能性があり、そのためにその義務を実行できず、状況全体が悪化します (事実上、HttpSession
s が決して期限切れ)。
上記の不幸なシナリオを緩和する方法はいくつかあります。どちらが理にかなっているのかは、要件と環境次第です。
ヒープ サイズを増やします。これは明らかにこれまでのところしか得られません。関連するオブジェクトで16GiB ヒープをいっぱいにする場合HttpSession
、コモディティ ハードウェアの限界に達しており、単純に大きな箱を購入することはできません。
セッションの有効期限を短縮します (デフォルトは 30 分です)。セッションが明示的に終了されていない場合 (たとえば、ログアウト関数によって)、HttpSession
オブジェクトとそのすべてのコンテンツは、有効期限が過ぎるまで残ります。放棄された多くのセッションに大量のデータがある場合、セッションの有効期限を短縮すると、息抜きの余地が生じる場合があります。
ユーザーの に大量のデータを入れるのはやめましょうHttpSession
。これは不愉快な提案のように思えるかもしれませんが (「それをやめてください」)、正直なところ有効な提案です: セッション自体にそんなに多くのものを保存する必要があるのでしょうか? ある種のデータ ストア (リレーショナル データベース、Cassandra のような非リレーショナル データベース、webcache など) を使用するのはどうですか? 多分データをディスク上のファイルに保存しますか?これらの提案は、データにすばやくアクセスする能力を確かに制限しますが、セッション内の非常に多くのものの重みでサーバーがクラッシュするよりは確実に優れたオプションです.
Tomcat の を使用しますPersistentManager
。これは、アクティブな (ただしアイドル状態の) セッションを外部ストレージにスワップできるセッション マネージャーです (ファイル ベースおよび JDBC ベースのストレージ メカニズムはデフォルトで利用可能です)。これにより、ユーザーのセッションに押し込んでいるすべてのデータを配置する別の場所を見つけるまでに、長い道のりを歩むことができます。
4 を除くすべてのサーブレット コンテナに適用できます。#4 は、JBoss が内部で Tomcat を使用しているため、JBoss ユーザーが利用できるはずです。他のコンテナについても、同様の機能が存在することがあります。