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 Context
elemento 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:
- Aumentar la caché (recomendado)
- Bajar el TTL (no recomendado)
- Suprimir las advertencias del registro de caché (no recomendado)
- 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 Context
elemento 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.xml
dentro del Server
elemento:
<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" />
y descárguelo catalina-jmx-remote.jar
de 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 cacheTtl
valor 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 cachingAllowed
en 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).