Lancio di Tomcat 8 - org.apache.catalina.webresources.Cache.getResource Impossibile aggiungere la risorsa


111

Ho appena aggiornato Tomcat dalla versione 7.0.52 alla 8.0.14.

Lo ricevo per molti file di immagini statiche:

org.apache.catalina.webresources.Cache.getResource Impossibile aggiungere la risorsa in [/base/1325/WA6144-150x112.jpg] alla cache perché lo spazio disponibile era insufficiente dopo aver eliminato le voci della cache scadute: valuta la possibilità di aumentare la dimensione massima della cache

Non ho specificato alcuna impostazione particolare delle risorse e non l'ho ricevuta per 7.0.52.

Ho trovato menzione di ciò che accade all'avvio in una segnalazione di bug che sarebbe stata risolta. Per me questo non accade all'avvio ma costantemente quando viene richiesta la risorsa.

Qualcun altro ha questo problema?

Sto cercando di disabilitare almeno la cache, ma non riesco a trovare un esempio di 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 corretta.

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

Grazie.


Nessuna risposta: immagino di essere l'unica persona con questo problema.
iainmac999


1
Per quanto riguarda l'attributo mancante nel contesto Tomcat 8, ecco un estratto dalla guida alla migrazione (enfasi mia): " Il refactoring delle risorse ha anche comportato la rimozione di una serie di attributi dall'implementazione del contesto predefinita (org.apache.catalina.core .StandardContext). I seguenti attributi possono ora essere configurati tramite l'implementazione delle risorse utilizzate dall'applicazione web ". Maggiori informazioni nella relativa guida alla migrazione .
informatik01

@ iainmac999 non avendo mai selezionato una risposta corretta dopo 2 anni possiamo essere d'accordo che funziona in entrambi i modi?
davidjmcclelland

Risposte:


161

Nel tuo $CATALINA_BASE/conf/context.xmlblocco aggiungi qui sotto prima</Context>

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

Per ulteriori informazioni: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html


11
I singoli lettori probabilmente vorranno regolare il valore cacheMaxSize su qualcosa di meno di 100 mega.
Eric Spiegelberg,

finora il messaggio di errore stava inondando i miei log della console. Ora è chiaro. Grazie
Abubacker Siddik

152

Ho riscontrato lo stesso problema durante l'aggiornamento da Tomcat 7 a 8: un flusso continuo di avvisi di registro sulla cache.

1. Risposta breve

Aggiungi questo all'interno Contextdell'elemento 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 valore predefinito è 10240(10 mbyte), quindi imposta una dimensione superiore a questa. Quindi sintonizzare per impostazioni ottimali in cui gli avvisi scompaiono. Tieni presente che gli avvisi potrebbero ripresentarsi in situazioni di traffico 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 al TTL di tali voci. Quindi Tomcat non aveva abbastanza voci di cache da poter scadere, perché erano troppo recenti, quindi non poteva liberare abbastanza cache e quindi emette avvisi.

Il problema non è apparso in Tomcat 7 perché Tomcat 7 semplicemente non ha emesso avvisi in questa situazione. (Inducendo te e me a utilizzare impostazioni della cache scadenti senza essere avvisati.)

Il problema si verifica quando si riceve una quantità relativamente grande di richieste HTTP di risorse (solitamente statiche) in un periodo di tempo relativamente breve rispetto alle dimensioni e al TTL della cache. Se la cache sta raggiungendo il suo massimo (10 MB per impostazione predefinita) con più del 95% delle sue dimensioni con nuove voci di cache (fresco significa meno di 5 secondi nella cache), riceverai un messaggio di avviso per ogni risorsa web che Tomcat prova da caricare nella cache.

1.2 Informazioni opzionali

Utilizzare JMX se è necessario ottimizzare 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

Un 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) è per impostazione predefinita 10240 kbyte (10 mbyte). Una webResource viene caricata nella cache quando viene richiesta la webResource (ad esempio quando si carica un'immagine statica), viene quindi chiamata una 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 il TTL scade, la voce della cache può essere rimossa dalla cache. Il valore predefinito di cacheTTL è 5000 millisecondi (5 secondi).

C'è altro da dire sulla memorizzazione nella cache, ma questo è irrilevante per il problema.

2.2 La causa

Il codice seguente della classe Cache mostra i criteri di memorizzazione nella cache in dettaglio:

152   // Il contenuto non verrà memorizzato nella cache ma abbiamo ancora bisogno della dimensione dei metadati 
153 long delta = cacheEntry. getSize ();
154 dimensioni. addAndGet (delta);
156 if (size. Get ()> maxSize) {
157 // Elabora risorse non ordinate per la velocità. Cache delle transazioni
158 // efficienza (le voci più giovani possono essere rimosse prima delle
159 // precedenti) per la velocità poiché si trova sul percorso critico per
160 // elaborazione della richiesta
161 long targetSize =
162 maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100;
163 lungo newSize = EVICT (
164 . TargetSize, resourcecache valori (). Iterator ());
165 if (newSize> maxSize) {
166 // Impossibile creare spazio sufficiente per questa risorsa
167 // Rimuoverla dalla cache
168 removeCacheEntry (path);
169 log. warn (sm. getString ("cache.addFail", path));
170 }
171 }

Quando si carica un webResource, 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à quella massima. Quindi il codice calcolerà un "targetSize", che è la dimensione sotto la quale la cache vuole rimanere (come ottimale), che è per impostazione predefinita il 95% del massimo. Per raggiungere questo targetSize, le voci devono essere rimosse / eliminate dalla cache. Questo viene fatto utilizzando il codice seguente:

215   private  long evict ( long targetSize, Iterator < CachedResource > iter) { 
217 long now = System. currentTimeMillis ();
219 lungo nuovoSize = size. get ();
221 while (newSize> targetSize && iter. HasNext ()) {
222 CachedResource resource = iter. successivo ();
224 // Non far scadere nulla che è stato controllato nel TTL
225 se (resource. GetNextCheck ()> now) {
226 continuare ;
227 }
229 // Rimuove la voce dalla cache
230 removeCacheEntry (resource. GetWebappPath ());
232 newSize = dimensione. get ();
233 }
235 return newSize;
236 }

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

Dopo il tentativo di liberare la cache rimuovendo le voci della cache, il codice farà:

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

Quindi, se dopo il tentativo di liberare la cache, la dimensione supera ancora il massimo, verrà visualizzato il messaggio di avviso sull'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 libero insufficiente disponibile dopo aver eliminato le voci della cache scadute: prendere in considerazione l'aumento della dimensione massima della cache

Se la tua applicazione web carica molte risorse web non memorizzate nella cache (circa il massimo della cache, per impostazione predefinita 10 MB) in breve tempo (5 secondi), riceverai l'avviso.

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

1606   // Aggiungi nuova voce nella cache 
1607 sincronizzato (cache) {
1608 // Controllare la dimensione della cache, e gli elementi di rimuovere, se troppo grande
1609 se ((cache. Lookup (nome) == nullo ) && cache. Allocare (entry.size) ) {
1610 cache. carico (entrata);
1611 }
1612 }

combinata con:

231   while (toFree> 0) { 
232 if (tempt == maxAllocateIterations) {
233 // Rinuncia, non vengono apportate modifiche alla cache
234 corrente return false ;
235 }

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

Quindi, se stai utilizzando Tomcat 8 con la stessa configurazione di memorizzazione nella cache predefinita di Tomcat 7 e hai ricevuto avvisi in Tomcat 8, le tue (e mie) impostazioni di memorizzazione nella cache di Tomcat 7 funzionavano male senza preavviso.

2.4 Soluzioni

Esistono molteplici soluzioni:

  1. Aumenta la cache (consigliato)
  2. Abbassare il TTL (non consigliato)
  3. Elimina gli avvisi del registro della cache (non consigliato)
  4. Disabilitare la cache

2.4.1. Aumenta la cache (consigliato)

Come descritto qui: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html

Aggiungendo <Resources cacheMaxSize="XXXXX" />all'interno Contextdell'elemento in $CATALINA_BASE/conf/context.xml, dove "XXXXX" sta per una maggiore dimensione della cache, specificata in kbyte. L'impostazione predefinita è 10240 (10 mbyte), quindi imposta una dimensione superiore a questa.

Dovrai sintonizzarti per impostazioni ottimali. Tieni presente che il problema potrebbe ripresentarsi quando improvvisamente si verifica un aumento del traffico / delle richieste di 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 , aggiungilo $CATALINA_BASE/conf/server.xmlall'interno Serverdell'elemento: <Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" />e scaricalo catalina-jmx-remote.jarda https://tomcat.apache.org/download-80.cgi e inseriscilo $CATALINA_HOME/lib. Quindi utilizzare jConsole (fornito per impostazione predefinita con Java JDK) per connettersi tramite JMX al server e controllare le impostazioni per le impostazioni per aumentare la dimensione della cache mentre il server è in esecuzione. Le modifiche a queste impostazioni dovrebbero avere effetto immediato.

2.4.2. Abbassare il TTL (non consigliato)

Abbassare il cacheTtlvalore di qualcosa al di sotto di 5000 millisecondi e regolare per impostazioni ottimali.

Per esempio: <Resources cacheTtl="2000" />

Ciò si riduce effettivamente ad avere e riempire una cache nella ram senza usarla.

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

Configurare la registrazione per disabilitare il logger per org.apache.catalina.webresources.Cache.

Per maggiori informazioni sull'accesso a Tomcat: http://tomcat.apache.org/tomcat-8.0-doc/logging.html

2.4.4. Disabilitare la cache

È possibile disabilitare la cache impostando cachingAllowedsu 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 disabilitazione della cache tramite server.xml.)


Aumentare la cache? Dubito che avrebbe funzionato ... Ho visto questo: private long maxSize = 10 * 1024 * 1024; nella sorgente. grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/…
HoaPhan

hai trovato la risposta al motivo per cui tomcat8 sta inondando gli avvisi della cache
PHP Avenger

@HoaPhan 10 * 1024 * 1024 è un massimo di 10 MB per tutta la cache in totale. A seconda del traffico della webapp, questo può essere raggiunto in pochi secondi. Aumentarlo abbastanza lontano, funzionerà.
Devabc

@PHPAvenger Tomcat 7 non ha avvisato affatto in questa posizione, mentre Tomcat 8 lo fa, quindi può essere visto come una funzione di avviso. Il problema è che avvisa non solo una volta, ma su ogni richiesta di risorsa da memorizzare nella cache. Sarebbe un miglioramento avvisare solo dopo un certo periodo di tempo o memorizzare nella cache gli hit.
Devabc

@ Devabc risposta impeccabile! Un classico così!
gaurav

9

Hai più risorse statiche per le quali la cache ha spazio. Puoi eseguire una delle seguenti operazioni:

  • Aumenta la dimensione della cache
  • Diminuisci il TTL per la cache
  • Disabilita la memorizzazione nella cache

Per maggiori dettagli vedere la documentazione di queste opzioni di configurazione.


1
Grazie per il commento. Capisco il significato dell'eccezione e ovviamente ho letto la documentazione a cui ti sei collegato, tuttavia non capisco perché questo cambierebbe da 7 a 8 senza modifiche alla configurazione. Cioè, perché il gestore delle risorse del file system predefinito dovrebbe essere diverso da 8 a 7, senza riferimento ad alcuna modifica, ed è sospetto che un bug di avvio sia stato segnalato e presumibilmente corretto.
iainmac999

1
Forse se avessi letto la guida alla migrazione, in particolare tomcat.apache.org/migration-8.html#Web_application_resources , le cose sarebbero più chiare.
Mark Thomas

Sarebbe utile se la documentazione facesse un po 'di più per a) spiegare quali risorse vanno in questa cache e perché (molti malintesi abbondano su questo!) Eb) quale impatto possono avere le diverse impostazioni (ad esempio, semplicemente facendo ciecamente l'impostazione della cache di ogni webapp abbastanza grande può mangiare un sacco di memoria) e come sintonizzarlo correttamente. Sarebbe anche utile se ci fosse una distinzione nel codice e nella configurazione tra la memorizzazione nella cache delle risorse statiche utilizzate dall'applicazione stessa rispetto ai file statici richiesti dai programmi utente e semplicemente forniti dall'applicazione.
volkerk

4

Questa non è una soluzione nel senso che non risolve le condizioni che causano la visualizzazione del messaggio nei log, ma il messaggio può essere soppresso aggiungendo quanto segue a conf/logging.properties:

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

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

A mio avviso a WARNINGnon è necessariamente un errore che deve essere affrontato, ma piuttosto può essere ignorato se lo si desidera.


8
Haha. questo non risolve il problema. Semplicemente non lo mostra. WTF!
T3rm1

Questo risolve il problema della registrazione eccessiva, che può essere un problema significativo di per sé. Ritorna al comportamento delle versioni precedenti di Tomcat, in cui le cose funzionavano sufficientemente bene per molti, quindi in quel senso "risolve" il problema. Non risolve il problema dell'effettiva messa a punto della cache di Tomcat, che la risposta di devabc copre molto bene.
volkerk
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.