risposta-alla-domanda-sullo-sviluppo-web-bd.com

Tomcat 8 throwing - org.Apache.catalina.webresources.Cache.getResource Impossibile aggiungere la risorsa

Ho appena aggiornato Tomcat dalla versione 7.0.52 alla 8.0.14.

Sto ottenendo questo per un sacco di file di immagine statici:

org.Apache.catalina.webresources.Cache.getResource Impossibile aggiungere la risorsa in [/base/1325/WA6144-150x112.jpg] alla cache perché non c'era spazio disponibile sufficiente dopo aver rimosso le voci della cache scadute: prendere in considerazione l'aumento della dimensione massima della cache

Non ho specificato alcuna particolare impostazione di risorse, e non ho avuto questo per 7.0.52.

Ho trovato menzione di ciò che accade all'avvio in una segnalazione di bug che è stata presumibilmente corretta. Per me questo sta accadendo non all'avvio, ma costantemente quando viene richiesta la risorsa.

Qualcun altro ha questo problema?

Cercando di disabilitare almeno la cache, ma non riesco a trovare un esempio su come specificare di non utilizzare la cache. Gli attributi sono passati dal contesto in Tomcat versione 8. Ho provato ad aggiungere una risorsa ma non riesco a ottenere la configurazione giusta.

<Resource name="file" 
    cachingAllowed="false"
    className="org.Apache.catalina.webresources.FileResourceSet"
/>  

Grazie.

100
iainmac999

Nel tuo $CATALINA_BASE/conf/context.xml aggiungi il blocco sottostante prima di </Context>

<Resources cachingAllowed="true" cacheMaxSize="100000" />

Per maggiori informazioni: http://Tomcat.Apache.org/Tomcat-8.0-doc/config/resources.html

148
Destroyica

Ho avuto lo stesso problema durante l'aggiornamento da Tomcat 7 a 8: un flusso continuo di allarmi persistenti sulla cache.

1. Risposta breve

Aggiungi questo all'interno dell'elemento Context xml del tuo $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" />

Quindi il default è 10240 (10 mbyte), quindi imposta una dimensione più alta di questa. Quindi sintonizzare le impostazioni ottimali in cui gli avvisi scompaiono. Si noti che gli avvisi potrebbero tornare in situazioni di traffico più elevato.

1.1 La causa (breve spiegazione)

Il problema è causato dal fatto che Tomcat non è in grado di raggiungere la dimensione della cache di destinazione a causa di voci della cache inferiori a TTL di tali voci. Quindi Tomcat non aveva abbastanza voci della cache che poteva scadere, perché erano troppo fresche, quindi non poteva liberare abbastanza cache e quindi emettere avvisi.

Il problema non è apparso in Tomcat 7 perché Tomcat 7 semplicemente non ha emesso avvisi in questa situazione. (Fare in modo che tu e io usiamo impostazioni della cache scadenti senza essere avvisati).

Il problema si verifica quando si riceve una grande quantità relativa di richieste HTTP per risorse (in genere statiche) in un periodo di tempo relativamente breve rispetto alla dimensione e TTL della cache. Se la cache raggiunge il massimo (10mb per impostazione predefinita) con più del 95% delle sue dimensioni con nuove voci della cache (fresche significa meno di 5 secondi in cache), verrà visualizzato un messaggio di avviso per ogni risorsa Web che Tomcat tenta caricare nella cache.

1.2 Informazioni opzionali

Utilizzare JMX se è necessario sintonizzare cacheMaxSize su un server in esecuzione senza riavviarlo.

La soluzione più rapida sarebbe disabilitare completamente la cache: <Resources cachingAllowed="false" />, ma non è ottimale, quindi aumenta cacheMaxSize come ho appena descritto.

2. Risposta lunga

2.1 Informazioni di base

A WebSource è un file o una directory in un'applicazione web. Per motivi di prestazioni, Tomcat può memorizzare nella cache WebSources. Il massimo della cache delle risorse statiche (tutte le risorse in totale) è di default 10240 kbyte (10 mbyte). Una risorsa Web viene caricata nella cache quando viene richiesta la risorsa Web (ad esempio quando si carica un'immagine statica), quindi viene chiamata voce della cache. Ogni voce della cache ha un TTL (time to live), che è il tempo in cui la voce della cache può rimanere nella cache. Quando scade il TTL, la voce cache è idonea per essere rimossa dalla cache. Il valore predefinito di cacheTTL è 5000 millisecondi (5 secondi).

C'è altro da dire sul caching, ma questo è irrilevante per il problema.

2.2 La causa

Il seguente codice della classe Cache mostra in dettaglio la politica di memorizzazione nella cache:

152  // Il contenuto non verrà memorizzato nella cache, ma abbiamo ancora bisogno della dimensione dei metadati
153  lungo delta = cacheEntry. getSize ();
154 dimensione. addAndGet (delta);
156  se (dimensione. get ()> maxSize) {
157 // Elabora risorse non ordinate per la velocità. Cache commerciale
158 // efficienza (le voci più giovani possono essere sfrattate prima di età avanzata
159 // ones) per la velocità poiché questo è sul percorso critico per
160 // richiesta elaborazione
161  lungo targetSize =
162 maxSize * (100 - TARGET_FREE_PERCENT_GET)/100;
163  lungo newSize = sfratto (
164 targetSize, resourceCache. valori (). iteratore ());
165  se (newSize> maxSize) {
166 // Impossibile creare spazio sufficiente per questa risorsa
167 // Rimuoverlo dalla cache
168removeCacheEntry (percorso);
169 log. warn (sm. getString ("cache.addFail", percorso));
170 }
171 }

Quando si carica una risorsa Web, il codice calcola la nuova dimensione della cache. Se la dimensione calcolata è maggiore della dimensione massima predefinita, è necessario rimuovere una o più voci memorizzate nella cache, altrimenti la nuova dimensione supererà il limite massimo. Quindi il codice calcolerà un "target size", che è la dimensione in cui la cache vuole rimanere (come un ottimo), che è di default il 95% del massimo. Per raggiungere questo targetSize, le voci devono essere rimosse/sfrattate dalla cache. Questo viene fatto usando il seguente codice:

215  privatolungo sfrattare(lungo targetSize,  Iterator  < CachedResource > iter) {
217 ​​  lungo now = System. currentTimeMillis ();
219  lungo newSize = size. get ();
221  mentre (newSize> targetSize && iter. hasNext ()) {
222CachedResource resource = iter. accanto ();
224 // Non fa scadere nulla che è stato controllato all'interno del TTL
225  se (risorsa. getNextCheck ()> ora) {
226  continua;
227 }
229 // Rimuovi la voce dalla cache
230removeCacheEntry (risorsa. getWebappPath ());
232 newSize = size. get ();
233 }
235  ritorno newSize;
236 }

Quindi una voce cache viene rimossa quando il suo TTL è scaduto e il targetSize non è stato ancora raggiunto.

Dopo aver tentato di liberare la cache rimuovendo le voci della cache, il codice eseguirà:

165  se (newSize> maxSize) {
166 // Impossibile creare spazio sufficiente per questa risorsa
167 // Rimuoverlo dalla cache
168removeCacheEntry (percorso);
169 log. warn (sm. getString ("cache.addFail", percorso));
170 }

Quindi, se dopo il tentativo di liberare la cache, la dimensione supera ancora il massimo, mostrerà il messaggio di avviso relativo all'impossibilità di liberare:

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 Il problema

Quindi, come dice il messaggio di avviso, il problema è

spazio disponibile insufficiente dopo aver rimosso le voci della cache scadute - considerare di aumentare la dimensione massima della cache

Se l'applicazione Web carica un sacco di risorse Web non collegate (circa il massimo di cache, per impostazione predefinita 10mb) entro un breve periodo di tempo (5 secondi), verrà visualizzato l'avviso.

La parte confusa è che Tomcat 7 non ha mostrato l'avviso. Questo è semplicemente causato da questo codice Tomcat 7:

1606  // Aggiungi una nuova voce alla cache
1607  sincronizzato (cache) {
1608 // Controlla la dimensione della cache e rimuovi gli elementi se troppo grandi
1609  se ((cache. ricerca (nome) == nullo) && cache. allocate (entry.size)) {
1610 cache. load (voce);
1611 }
1612 }

combinati con:

231  mentre (toFree> 0) {
232  se (tentativi == maxAllocateIterations) {
233 // Rinuncia, non vengono apportate modifiche alla cache corrente
234  ritornofalse;
235 }

Quindi Tomcat 7 semplicemente non emette alcun avviso quando non è in grado di liberare la cache, mentre Tomcat 8 emette un avviso.

Quindi, se stai utilizzando Tomcat 8 con la stessa configurazione di cache predefinita di Tomcat 7 e ricevi avvisi in Tomcat 8, le tue (e mie) impostazioni di cache di Tomcat 7 si stanno comportando male senza preavviso.

2.4 Soluzioni

Ci sono più soluzioni:

  1. Aumentare la cache (consigliato)
  2. Abbassa il TTL (non consigliato)
  3. Elimina gli avvisi del registro di cache (non consigliato)
  4. Disabilitare la cache

2.4.1. Aumentare la cache (consigliato)

Come descritto qui: http://Tomcat.Apache.org/Tomcat-8.0-doc/config/resources.html

Aggiungendo <Resources cacheMaxSize="XXXXX" /> all'interno dell'elemento Context in $CATALINA_BASE/conf/context.xml, dove "XXXXX" rappresenta una dimensione della cache maggiore, specificata in kbyte. Il valore predefinito è 10240 (10 mbyte), quindi impostare una dimensione più alta di questa.

Dovrai sintonizzare per le impostazioni ottimali. Si noti che il problema può tornare quando si ha improvvisamente un aumento delle richieste di traffico/risorse.

Per evitare di dover riavviare il server ogni volta che si desidera provare una nuova dimensione della cache, è possibile modificarla senza riavviare utilizzando JMX.

Per abilitare JMX , aggiungere questo a $CATALINA_BASE/conf/server.xml all'interno dell'elemento Server: <Listener className="org.Apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" /> e scaricare catalina-jmx-remote.jar da https: // Tomcat . Apache.org/download-80.cgi e inseriscilo in $CATALINA_HOME/lib. Quindi utilizzare jConsole (fornito di default con Java JDK) per connettersi tramite JMX al server e cercare tra le impostazioni per aumentare le dimensioni della cache mentre il server è in esecuzione. Le modifiche a queste impostazioni dovrebbero avere effetto immediato.

2.4.2. Abbassa il TTL (non consigliato)

Abbassa il valore cacheTtl di qualcosa di inferiore a 5000 millisecondi e ottimizza le impostazioni ottimali.

Ad esempio: <Resources cacheMaxSize="2000" />

Questo deriva in effetti dall'avere e riempire una cache in ram senza usarla.

2.4.3. Elimina gli avvisi del registro di cache (non consigliato)

Configura la registrazione per disabilitare il logger per org.Apache.catalina.webresources.Cache.

Per ulteriori informazioni sull'accesso a Tomcat: http://Tomcat.Apache.org/Tomcat-8.0-doc/logging.html

2.4.4. Disabilitare la cache

Puoi disabilitare la cache impostando cachingAllowed a false. <Resources cachingAllowed="false" />

Anche se posso ricordare che in una versione beta di Tomcat 8, stavo usando JMX per disabilitare la cache. (Non sono sicuro del perché esattamente, ma potrebbe esserci un problema con la disattivazione della cache tramite server.xml.)

107
Devabc

Hai più risorse statiche di cui la cache ha spazio. Puoi fare una delle seguenti azioni:

  • Aumentare la dimensione della cache
  • Diminuisci il TTL per la cache
  • Disabilitare la cache

Per maggiori dettagli consultare la documentazione per queste opzioni di configurazione.

9
Mark Thomas

Nel caso in cui aiuti qualcun altro, l'unico modo in cui sono riuscito a risolvere questo problema è stato quello di aggiungere quanto segue a conf/logging.properties:

org.Apache.catalina.webresources.Cache.level = SEVERE

Questo filtra i registri "Impossibile aggiungere la risorsa", che sono al livello ATTENZIONE.

6
Geoffrey Booth