Lanzamiento de Tomcat 8 - org.apache.catalina.webresources.Cache.getResource No se puede agregar el recurso

111

Acabo de actualizar Tomcat de la versión 7.0.52 a 8.0.14.

Obtengo esto para muchos archivos de imagen estática:

org.apache.catalina.webresources.Cache.getResource No se puede agregar el recurso a [/base/1325/WA6144-150x112.jpg] a la caché, porque no había suficiente espacio libre disponible después de desalojar entradas de caché expirados - Considere aumentar el tamaño máximo del caché

No he especificado ninguna configuración de recursos en particular, y no obtuve esto para 7.0.52.

Encontré una mención de que esto sucedía al inicio en un informe de error que supuestamente se solucionó. Para mí, esto no sucede al inicio, sino constantemente cuando se solicita el recurso.

¿Alguien más tiene este problema?

Intento al menos deshabilitar el caché, pero no puedo encontrar un ejemplo de cómo especificar que no se use el caché. Los atributos se han ido del contexto en la versión 8 de Tomcat. He intentado agregar un recurso, pero no puedo configurar correctamente.

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

Gracias.

iainmac999
fuente
Sin respuestas, supongo que debo ser la única persona con este problema.
iainmac999
2
La solución está aquí: serverfault.com/questions/644415/…
Dmitry
1
Con respecto al atributo que falta en el contexto de Tomcat 8, aquí hay un extracto de la guía de migración (el énfasis es mío): " La refactorización de recursos también ha resultado en la eliminación de una serie de atributos de la implementación de contexto predeterminada (org.apache.catalina.core .StandardContext). Los siguientes atributos ahora se pueden configurar a través de la implementación de recursos utilizada por la aplicación web ". Más información en la guía de migración relacionada .
informatik01
@ iainmac999 sin haber seleccionado nunca una respuesta correcta después de 2 años, ¿podemos estar de acuerdo en que funciona en ambos sentidos?
davidjmcclelland

Respuestas:

161

En su $CATALINA_BASE/conf/context.xmlbloque de agregar a continuación antes</Context>

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

Para más información: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html

Destroyica
fuente
11
Es probable que los lectores individuales quieran ajustar ese valor de cacheMaxSize a algo menos de 100 megas.
Eric Spiegelberg
Hasta ahora, el mensaje de error inundaba los registros de mi consola. Ahora está claro. Gracias
Abubacker Siddik
152

Tuve el mismo problema al actualizar de Tomcat 7 a 8: una gran cantidad de advertencias de registro sobre la caché.

1. Respuesta corta

Agregue esto dentro del Contextelemento xml de su $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" />

Entonces, el valor predeterminado es 10240(10 mbyte), así que configure un tamaño más alto que este. Luego sintonice los ajustes óptimos donde desaparecen las advertencias. Tenga en cuenta que las advertencias pueden aparecer en situaciones de mayor tráfico.

1.1 La causa (breve explicación)

El problema se debe a que Tomcat no puede alcanzar su tamaño de caché de destino debido a que las entradas de caché son menores que el TTL de esas entradas. Entonces, Tomcat no tenía suficientes entradas de caché que pudieran caducar, porque estaban demasiado recientes, por lo que no podía liberar suficiente caché y, por lo tanto, genera advertencias.

El problema no apareció en Tomcat 7 porque Tomcat 7 simplemente no emitió advertencias en esta situación. (Haciendo que usted y yo usemos una configuración de caché deficiente sin ser notificados).

El problema aparece cuando se recibe una cantidad relativamente grande de solicitudes HTTP de recursos (generalmente estáticos) en un período de tiempo relativamente corto en comparación con el tamaño y TTL de la caché. Si el caché está alcanzando su máximo (10 MB de forma predeterminada) con más del 95% de su tamaño con entradas de caché nuevas (nuevo significa menos de 5 segundos en caché), recibirá un mensaje de advertencia para cada recurso web que Tomcat intente para cargar en la caché.

1.2 Información opcional

Utilice JMX si necesita ajustar cacheMaxSize en un servidor en ejecución sin reiniciarlo.

La solución más rápida sería deshabilitar completamente la caché:, <Resources cachingAllowed="false" />pero eso es subóptimo, así que aumente cacheMaxSize como acabo de describir.

2. Respuesta larga

2.1 Información general

Un WebSource es un archivo o directorio en una aplicación web. Por motivos de rendimiento, Tomcat puede almacenar en caché WebSources. El máximo de la caché de recursos estáticos (todos los recursos en total) es por defecto 10240 kbyte (10 mbyte). Un webResource se carga en el caché cuando se solicita el webResource (por ejemplo, cuando se carga una imagen estática), luego se denomina entrada de caché. Cada entrada de la caché tiene un TTL (tiempo de vida), que es el tiempo que la entrada de la caché puede permanecer en la caché. Cuando el TTL expira, la entrada de la caché es elegible para ser eliminada de la caché. El valor predeterminado de cacheTTL es 5000 milisegundos (5 segundos).

Hay más que contar sobre el almacenamiento en caché, pero eso es irrelevante para el problema.

2.2 La causa

El siguiente código de la clase Cache muestra la política de almacenamiento en caché en detalle:

152   // El contenido no se almacenará en caché pero aún necesitamos el tamaño de los metadatos 
153 long delta = cacheEntry. getSize ();
154 tamaño. addAndGet (delta);
156 if (size. Get ()> maxSize) {
157 // Procesar recursos desordenados por velocidad. Trades cache
158 // eficiencia (las entradas más jóvenes pueden ser desalojadas antes que las
159 // más antiguas ) para mayor velocidad ya que se encuentra en la ruta crítica para
160 // procesamiento de solicitudes
161 long targetSize =
162 maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100;
163 largo newSize = desalojar (
164 . TargetSize, resourceCache valores (). Iterador ());
165 if (newSize> maxSize) {
166 // No se puede crear suficiente espacio para este recurso
167 // Eliminarlo de la caché
168 removeCacheEntry (ruta);
169 log. advertir (sm. getString ("cache.addFail", ruta));
170 }
171 }

Al cargar un webResource, el código calcula el nuevo tamaño de la caché. Si el tamaño calculado es mayor que el tamaño máximo predeterminado, se deben eliminar una o más entradas almacenadas en caché; de lo contrario, el nuevo tamaño superará el máximo. Entonces, el código calculará un "targetSize", que es el tamaño bajo el que la caché quiere permanecer (como un óptimo), que es por defecto el 95% del máximo. Para alcanzar este targetSize, las entradas deben eliminarse / desalojarse de la caché. Esto se hace usando el siguiente código:

215   desalojo largo privado  ( tamaño de destino largo , iterador < CachedResource > iter) { 217 largo ahora = System. currentTimeMillis (); 219 largo newSize = tamaño. obtener (); 221 while (newSize> targetSize && iter. HasNext ()) { 222 CachedResource resource = iter. siguiente (); 224           // No expire nada de lo que se haya verificado dentro del TTL 225 if (resource. GetNextCheck ()> now) { 226






continuar ;
227 }
229 // Elimina la entrada de la caché
230 removeCacheEntry (resource. GetWebappPath ());
232 nuevoTamaño = tamaño. obtener ();
233 }
235 return newSize;
236 }

Por lo tanto, una entrada de caché se elimina cuando su TTL expira y aún no se ha alcanzado el targetSize.

Después del intento de liberar la caché desalojando las entradas de la caché, el código funcionará:

165   if (newSize> maxSize) { 
166 // No se puede crear suficiente espacio para este recurso
167 // Eliminarlo de la caché
168 removeCacheEntry (ruta);
169 log. advertir (sm. getString ("cache.addFail", ruta));
170 }

Entonces, si después del intento de liberar la caché, el tamaño aún excede el máximo, mostrará el mensaje de advertencia sobre no poder liberar:

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

Entonces, como dice el mensaje de advertencia, el problema es

espacio libre insuficiente disponible después de expulsar las entradas caducadas de la caché; considere aumentar el tamaño máximo de la caché

Si su aplicación web carga una gran cantidad de recursos web no almacenados en caché (aproximadamente el máximo de caché, por defecto 10 MB) en un corto período de tiempo (5 segundos), recibirá la advertencia.

La parte confusa es que Tomcat 7 no mostró la advertencia. Esto es causado simplemente por este código de Tomcat 7:

1606   // Añadir nueva entrada a la memoria caché 
1607 sincronizada (caché) {
1608 // Comprobar tamaño de la caché, y los elementos de quitar si es demasiado grande
1609 si ((caché. Lookup (nombre) == nula ) && caché. Asignar (entry.size) ) {
1610 caché. carga (entrada);
1611 }
1612 }

combinado con:

231   while (toFree> 0) { 
232 if (intentos == maxAllocateIterations) {
233 // Ríndete , no se realizan cambios en la caché actual
234 return false ;
235 }

Por lo tanto, Tomcat 7 simplemente no genera ninguna advertencia cuando no puede liberar el caché, mientras que Tomcat 8 generará una advertencia.

Entonces, si está utilizando Tomcat 8 con la misma configuración de almacenamiento en caché predeterminada que Tomcat 7, y recibió advertencias en Tomcat 8, entonces su configuración de almacenamiento en caché (y la mía) de Tomcat 7 funcionaba mal sin advertencia.

2.4 Soluciones

Existen múltiples soluciones:

  1. Aumentar la caché (recomendado)
  2. Bajar el TTL (no recomendado)
  3. Suprimir las advertencias del registro de caché (no recomendado)
  4. Desactivar el caché

2.4.1. Aumentar la caché (recomendado)

Como se describe aquí: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html

Añadiendo <Resources cacheMaxSize="XXXXX" />dentro del Contextelemento in $CATALINA_BASE/conf/context.xml, donde "XXXXX" representa un tamaño de caché aumentado, especificado en kbytes. El valor predeterminado es 10240 (10 mbyte), así que configure un tamaño superior a este.

Tendrá que sintonizar la configuración óptima. Tenga en cuenta que el problema puede volver a aparecer cuando de repente tenga un aumento en las solicitudes de tráfico / recursos.

Para evitar tener que reiniciar el servidor cada vez que desee probar un nuevo tamaño de caché, puede cambiarlo sin reiniciar utilizando JMX.

Para habilitar JMX , agregue esto $CATALINA_BASE/conf/server.xmldentro del Serverelemento: <Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" />y descárguelo catalina-jmx-remote.jarde https://tomcat.apache.org/download-80.cgi e introdúzcalo $CATALINA_HOME/lib. Luego use jConsole (enviado de manera predeterminada con Java JDK) para conectarse a través de JMX al servidor y busque en la configuración la configuración para aumentar el tamaño de la caché mientras el servidor se está ejecutando. Los cambios en esta configuración deberían surtir efecto de inmediato.

2.4.2. Bajar el TTL (no recomendado)

Disminuya el cacheTtlvalor en algo menos de 5000 milisegundos y ajústelo para una configuración óptima.

Por ejemplo: <Resources cacheTtl="2000" />

Esto se reduce efectivamente a tener y llenar un caché en RAM sin usarlo.

2.4.3. Suprimir las advertencias del registro de caché (no recomendado)

Configure el registro para deshabilitar el registrador org.apache.catalina.webresources.Cache.

Para obtener más información sobre cómo iniciar sesión en Tomcat: http://tomcat.apache.org/tomcat-8.0-doc/logging.html

2.4.4. Desactivar el caché

Puede deshabilitar la caché estableciendo cachingAlloweden false. <Resources cachingAllowed="false" />

Aunque puedo recordar que en una versión beta de Tomcat 8, estaba usando JMX para deshabilitar el caché. (No estoy seguro de por qué exactamente, pero puede haber un problema al deshabilitar la caché a través de server.xml).

Devabc
fuente
¿Aumentar la caché? Dudo que funcione ... Vi esto: private long maxSize = 10 * 1024 * 1024; en la fuente. grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/…
HoaPhan
¿Encontraste la respuesta a por qué tomcat8 está inundando advertencias de caché?
PHP Avenger
@HoaPhan 10 * 1024 * 1024 es un máximo de 10 MB para todo el caché en total. Dependiendo del tráfico de la aplicación web, esto se puede alcanzar en segundos. Aumentarlo lo suficiente funcionará.
Devabc
@PHPAvenger Tomcat 7 no advirtió en absoluto en esta situación, mientras que Tomcat 8 sí, por lo que puede verse como una característica de advertencia. El problema es que advierte no solo una vez, sino sobre cada solicitud de recursos de almacenamiento en caché. Sería una mejora advertir solo después de una cierta cantidad de tiempo o almacenar en caché los impactos del objetivo.
Devabc
@Devabc ¡respuesta impecable! ¡Un TAN clásico!
gaurav
9

Tienes más recursos estáticos para los que la caché tiene espacio. Puede realizar una de las siguientes acciones:

  • Incrementar el tamaño del caché
  • Disminuir el TTL de la caché
  • Deshabilitar el almacenamiento en caché

Para obtener más detalles, consulte la documentación de estas opciones de configuración.

Mark Thomas
fuente
1
Gracias por el comentario. Entiendo el significado de la excepción y, por supuesto, leí la documentación a la que se vinculó, sin embargo, no entiendo por qué esto cambiaría de 7 a 8 sin cambios de configuración. Es decir, ¿por qué el controlador de recursos del sistema de archivos predeterminado sería diferente en 8 a 7, sin referencia a ningún cambio, y es sospechoso que se informó y supuestamente se corrigió un error de inicio?
iainmac999
1
Quizás si hubiera leído la guía de migración, específicamente tomcat.apache.org/migration-8.html#Web_application_resources , las cosas estarían más claras.
Mark Thomas
Sería útil si la documentación hiciera un poco más para a) explicar qué recursos van a esta caché y por qué (¡abundan muchos malentendidos al respecto!) Yb) qué impacto pueden tener las diferentes configuraciones (por ejemplo, simplemente hacer ciegamente la configuración de la caché de cada aplicación web bastante grande puede comer una tonelada de memoria) y cómo ajustar esto correctamente. También ayudaría si hubiera una distinción en el código y la configuración entre el almacenamiento en caché de los recursos estáticos utilizados por la propia aplicación frente a los archivos estáticos solicitados por los agentes de usuario y simplemente entregados por la aplicación.
volkerk
4

Esta no es una solución en el sentido de que no resuelve las condiciones que hacen que el mensaje aparezca en los registros, pero el mensaje se puede suprimir agregando lo siguiente a conf/logging.properties:

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

Esto filtra los registros "No se puede agregar el recurso", que se encuentran en el nivel ADVERTENCIA.

En mi opinión, a WARNINGno es necesariamente un error que deba abordarse, sino que se puede ignorar si se desea.

Stand de Geoffrey
fuente
8
Jaja. esto no resuelve el problema. Simplemente no lo demuestra. ¡WTF!
T3rm1
Esto resuelve el problema de la tala excesiva, que puede ser un problema importante por sí solo. Vuelve al comportamiento de versiones anteriores de tomcat, donde las cosas funcionaron suficientemente bien para muchos, por lo que en ese sentido "resuelve" el problema. No aborda el problema de ajustar realmente la caché de tomcat, que la respuesta de devabc cubre muy bien.
volkerk