Tomcat 7 から 8 にアップグレードしたときに同じ問題が発生しました。キャッシュに関するログ警告が大量に連続して発生しました。
1.短い答え
Context
これを のxml 要素内に追加します$CATALINA_BASE/conf/context.xml
。
<!-- The default value is 10240 kbytes, even when not added to context.xml.
So increase it high enough, until the problem disappears, for example set it to
a value 5 times as high: 51200. -->
<Resources cacheMaxSize="51200" />
デフォルトは10240
(10mbyte)ですので、これよりも大きなサイズを設定してください。警告が消える最適な設定に調整するよりも。交通量が多い状況では、警告が再び表示される場合があることに注意してください。
1.1 原因(簡単な説明)
この問題は、キャッシュ エントリがそれらのエントリの TTL よりも小さいために、Tomcat がターゲット キャッシュ サイズに到達できないことが原因で発生します。そのため、Tomcat には有効期限が切れるほど十分なキャッシュ エントリがありませんでした。これは、それらが新鮮すぎるためです。そのため、十分なキャッシュを解放できず、警告が出力されます。
この問題は Tomcat 7 では発生しませんでした。これは、Tomcat 7 がこの状況で警告を出力しなかったためです。(あなたと私が通知なしに貧弱なキャッシュ設定を使用する原因となります。)
この問題は、キャッシュのサイズと TTL に比べて比較的短い時間内にリソース (通常は静的) に対する比較的大量の HTTP 要求を受信した場合に発生します。キャッシュが最大値 (デフォルトでは 10MB) に達し、そのサイズの 95% 以上が新しいキャッシュ エントリ (新しいとは、キャッシュ内で 5 秒未満であることを意味します) である場合、Tomcat が試行する webResource ごとに警告メッセージが表示されます。キャッシュにロードします。
1.2 オプション情報
実行中のサーバーを再起動せずに cacheMaxSize を調整する必要がある場合は、JMX を使用します。
一番手っ取り早いのは cache: を完全に無効にすることです<Resources cachingAllowed="false" />
が、それは最適ではないので、今説明したように cacheMaxSize を増やしてください。
2.長い答え
2.1 背景情報
WebSourceは、Web アプリケーション内のファイルまたはディレクトリです。パフォーマンス上の理由から、Tomcat は WebSource をキャッシュできます。静的リソース キャッシュ(すべてのリソースの合計)の最大値は、デフォルトで 10240 kbyte (10 mbyte) です。webResource は、webResource が要求されたときにキャッシュに読み込まれます (たとえば、静的イメージを読み込むとき)。キャッシュ エントリと呼ばれます。すべてのキャッシュ エントリにはTTL (存続時間) があります。これは、キャッシュ エントリがキャッシュにとどまることができる時間です。TTL が期限切れになると、キャッシュ エントリはキャッシュから削除できるようになります。cacheTTL のデフォルト値は 5000 ミリ秒 (5 秒) です。
キャッシングについてはまだ説明すべきことがありますが、それは問題とは関係ありません。
2.2 原因
Cache クラスの次のコードは、キャッシュ ポリシーの詳細を示しています。
152 // コンテンツはキャッシュされませんが、メタデータ サイズが必要です
153 long delta = cacheEntry. getSize ();
154 サイズ。addAndGet (デルタ);
156 if ( size.get () > maxSize) {
157 // 速度のために順序付けられていないリソースを処理します。 //これは160のクリティカル パス上にあるため、速度と引き換えにキャッシュ
158 // 効率 (古い
159 エントリの前に若いエントリが追い出される可能性があります) // リクエスト処理161 long targetSize = 162 maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100;
163 long newSize = evict ( 164
targetSize , resourceCache.values (). iterator ()); 165 if (newSize > maxSize) { 166 // このリソースに十分なスペースを作成できません167 // キャッシュから削除します168 removeCacheEntry (path); 169 ログ。warn ( sm.getString ("cache.addFail", path)); 170 } 171 }
webResource をロードするとき、コードはキャッシュの新しいサイズを計算します。計算されたサイズがデフォルトの最大サイズよりも大きい場合は、1 つ以上のキャッシュされたエントリを削除する必要があります。削除しないと、新しいサイズが最大サイズを超えてしまいます。したがって、コードは「targetSize」を計算します。これは、キャッシュが(最適として)下にとどめたいサイズであり、デフォルトでは最大値の 95% です。この targetSize に到達するには、エントリをキャッシュから削除/削除する必要があります。これは、次のコードを使用して行われます。
215 private long evict ( long targetSize, Iterator < CachedResource > iter) {
217 long now = System. currentTimeMillis ();
219 long newSize = サイズ。()を取得します。
221 while (newSize > targetSize && iter.hasNext ()) {
222 CachedResourceリソース = iter. 次の();
224 // TTL 内でチェックされたものを期限切れにしない
225 if (resource. getNextCheck () > now) {
226 続行します。
227 }
229 // キャッシュからエントリを削除します
230 removeCacheEntry (resource. getWebappPath ());
232 newSize = サイズ。()を取得します。
233 }
235 戻りnewSize;
236 }
そのため、TTL が期限切れになり、targetSize にまだ達していない場合、キャッシュ エントリは削除されます。
キャッシュ エントリを削除してキャッシュを解放しようとした後、コードは次のことを行います。
165 if (newSize > maxSize) {
166 // このリソースに十分なスペースを作成できません
167 // キャッシュから削除します
168 removeCacheEntry (path);
169 ログ。warn ( sm.getString ("cache.addFail", path));
170 }
そのため、キャッシュを解放しようとしてもサイズが最大値を超えている場合は、解放できないという警告メッセージが表示されます。
cache.addFail=Unable to add the resource at [{0}] to the cache for web application [{1}] because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache
2.3 問題
警告メッセージにあるように、問題は
期限切れのキャッシュ エントリを削除した後に使用できる空き容量が不足しています - キャッシュの最大サイズを増やすことを検討してください
Web アプリケーションが短時間 (5 秒) 内に大量のキャッシュされていない webResources (キャッシュの最大値、デフォルトでは約 10MB) をロードすると、警告が表示されます。
紛らわしい部分は、Tomcat 7 が警告を表示しなかったことです。これは、単に次の Tomcat 7 コードが原因です。
1606 // 新しいエントリをキャッシュに追加します
1607 synchronized (cache) {
1608 // キャッシュ サイズをチェックし、大きすぎる場合は要素を削除します
1609 if ((cache. lookup (name) == null ) && cache. allocate (entry.size) ) {
1610 キャッシュ。ロード(エントリ);
1611 }
1612 }
と組み合わせ:
231 while (toFree > 0) {
232 if (attempts == maxAllocateIterations) {
233 // 諦めます。現在のキャッシュは変更されません
234 return false ;
235 }
そのため、Tomcat 7 は、キャッシュを解放できない場合に警告をまったく出力しませんが、Tomcat 8 は警告を出力します。
したがって、Tomcat 7 と同じデフォルトのキャッシュ構成で Tomcat 8 を使用していて、Tomcat 8 で警告が表示された場合、Tomcat 7 の (および私の) キャッシュ設定は警告なしでパフォーマンスが低下していました。
2.4 ソリューション
複数の解決策があります。
- キャッシュを増やす (推奨)
- TTL を下げる (非推奨)
- キャッシュ ログの警告を抑制する (非推奨)
- キャッシュを無効にする
2.4.1. キャッシュを増やす (推奨)
ここで説明されているように: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html
の要素<Resources cacheMaxSize="XXXXX" />
内に追加します。ここで、「XXXXX」は増加したキャッシュ サイズを表し、キロバイトで指定されます。デフォルトは 10240 (10 メガバイト) ですので、それ以上のサイズを設定してください。Context
$CATALINA_BASE/conf/context.xml
最適な設定に調整する必要があります。トラフィック/リソース要求が突然増加すると、問題が再発する可能性があることに注意してください。
新しいキャッシュ サイズを試すたびにサーバーを再起動する必要がないように、JMX を使用して再起動せずに変更できます。
JMXを有効にするには、これを要素
$CATALINA_BASE/conf/server.xml
内に追加します: https://tomcat.apache.org/download-80.cgiからダウンロード して に配置します。次に、jConsole (デフォルトで Java JDK に付属) を使用して JMX 経由でサーバーに接続し、設定を調べて、サーバーの実行中にキャッシュ サイズを増やします。これらの設定の変更はすぐに反映されます。Server
<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" />
catalina-jmx-remote.jar
$CATALINA_HOME/lib
2.4.2. TTL を下げる (非推奨)
値cacheTtl
を 5000 ミリ秒未満に下げて、最適な設定に調整します。
例えば:<Resources cacheTtl="2000" />
これは事実上、キャッシュを使用せずに RAM に格納して埋めることに帰着します。
2.4.3. キャッシュ ログの警告を抑制する (非推奨)
のロガーを無効にするようにロギングを構成しorg.apache.catalina.webresources.Cache
ます。
Tomcat でのログインの詳細については、http: //tomcat.apache.org/tomcat-8.0-doc/logging.htmlを参照してください。
2.4.4. キャッシュを無効にする
cachingAllowed
に設定することで、キャッシュを無効にすることができますfalse
。
<Resources cachingAllowed="false" />
Tomcat 8 のベータ版では、JMX を使用してキャッシュを無効にしていたことを覚えています。(正確な理由はわかりませんが、server.xml 経由でキャッシュを無効にすると問題が発生する可能性があります。)