Lancer Tomcat 8 - org.apache.catalina.webresources.Cache.getResource Impossible d'ajouter la ressource

111

Je viens de mettre à jour Tomcat de la version 7.0.52 à 8.0.14.

J'obtiens ceci pour beaucoup de fichiers d'image statiques:

org.apache.catalina.webresources.Cache.getResource Impossible d'ajouter la ressource [/base/1325/WA6144-150x112.jpg] au cache car l'espace disponible est insuffisant après la suppression des entrées de cache expirées - envisagez d'augmenter la taille maximale du cache

Je n'ai spécifié aucun paramètre de ressource particulier et je ne l'ai pas obtenu pour la version 7.0.52.

J'ai trouvé la mention de ce qui se passe au démarrage dans un rapport de bogue qui aurait été corrigé. Pour moi, cela ne se produit pas au démarrage mais constamment lorsque la ressource est demandée.

Quelqu'un d'autre a ce problème?

Essayer au moins de désactiver simplement le cache, mais je ne trouve pas d'exemple sur la façon de spécifier de ne pas utiliser le cache. Les attributs ont disparu du contexte de la version 8 de Tomcat. J'ai essayé d'ajouter une ressource mais je n'arrive pas à obtenir la bonne configuration.

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

Merci.

iainmac999
la source
Aucune réponse - je suppose que je dois être la seule personne à avoir ce problème.
iainmac999
2
La solution est ici: serverfault.com/questions/644415/…
Dmitry
1
Concernant l'attribut manquant dans le contexte de Tomcat 8, voici un extrait du guide de migration (c'est moi qui souligne): " La refactorisation des ressources a également entraîné la suppression d' un certain nombre d'attributs de l'implémentation du contexte par défaut (org.apache.catalina.core .StandardContext). Les attributs suivants peuvent maintenant être configurés via l'implémentation des ressources utilisées par l'application web ". Plus d'informations dans le guide de migration associé .
informatik01 le
@ iainmac999 n'ayant jamais sélectionné une réponse correcte après 2 ans, nous pouvons convenir que cela fonctionne dans les deux sens?
davidjmcclelland

Réponses:

161

Dans votre $CATALINA_BASE/conf/context.xmlbloc d'ajout ci-dessous avant</Context>

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

Pour plus d'informations: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html

Destroyica
la source
11
Les lecteurs individuels voudront probablement ajuster cette valeur cacheMaxSize à quelque chose de moins de 100 Mo.
Eric Spiegelberg le
Jusqu'à présent, le message d'erreur inondait les journaux de ma console. Maintenant c'est clair. Merci
Abubacker Siddik
152

J'ai eu le même problème lors de la mise à niveau de Tomcat 7 à 8: un grand nombre continu d'avertissements de journal sur le cache.

1. Réponse courte

Ajoutez ceci dans l' Contextélément xml de votre $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" />

La valeur par défaut est donc 10240(10 Mo), définissez donc une taille plus élevée que cela. Ensuite, réglez les paramètres optimaux là où les avertissements disparaissent. Notez que les avertissements peuvent revenir dans des situations de trafic élevé.

1.1 La cause (brève explication)

Le problème est dû au fait que Tomcat ne peut pas atteindre sa taille de cache cible en raison d'entrées de cache inférieures au TTL de ces entrées. Ainsi, Tomcat n'avait pas assez d'entrées de cache pour expirer, car elles étaient trop fraîches, il ne pouvait donc pas libérer suffisamment de cache et génère donc des avertissements.

Le problème n'apparaît pas dans Tomcat 7 car Tomcat 7 n'a tout simplement pas généré d'avertissements dans cette situation. (Nous obligeant vous et moi à utiliser des paramètres de cache médiocres sans être avertis.)

Le problème apparaît lors de la réception d'une quantité relativement importante de requêtes HTTP pour des ressources (généralement statiques) dans un laps de temps relativement court par rapport à la taille et au TTL du cache. Si le cache atteint son maximum (10 Mo par défaut) avec plus de 95% de sa taille avec des entrées de cache fraîches (frais signifie moins de moins de 5 secondes dans le cache), vous recevrez un message d'avertissement pour chaque ressource Web que Tomcat essaie. à charger dans le cache.

1.2 Informations facultatives

Utilisez JMX si vous devez régler cacheMaxSize sur un serveur en cours d'exécution sans le redémarrer.

La solution la plus rapide serait de désactiver complètement le cache <Resources cachingAllowed="false" />:, mais ce n'est pas optimal, augmentez donc cacheMaxSize comme je viens de le décrire.

2. Réponse longue

2.1 Informations générales

Une WebSource est un fichier ou un répertoire dans une application Web. Pour des raisons de performances, Tomcat peut mettre en cache les WebSources. Le maximum du cache de ressources statiques (toutes les ressources au total) est par défaut de 10240 Ko (10 Mo). Un webResource est chargé dans le cache lorsque le webResource est demandé (par exemple lors du chargement d'une image statique), il est alors appelé une entrée de cache. Chaque entrée de cache a un TTL (time to live), qui est le temps pendant lequel l'entrée de cache est autorisée à rester dans le cache. Lorsque le TTL expire, l'entrée de cache est éligible pour être supprimée du cache. La valeur par défaut du cacheTTL est de 5 000 millisecondes (5 secondes).

Il y a plus à dire sur la mise en cache, mais cela n'a pas d'importance pour le problème.

2.2 La cause

Le code suivant de la classe Cache montre la stratégie de mise en cache en détail:

152   // Le contenu ne sera pas mis en cache mais nous avons toujours besoin de la taille des métadonnées 
153 long delta = cacheEntry. getSize ();
154 taille. addAndGet (delta);
156 if (size. Get ()> maxSize) {
157 // Processus de ressources non ordonné pour la vitesse. Trades cache
158 // efficacité (les entrées les plus récentes peuvent être expulsées avant les
159 // les plus anciennes) pour la vitesse car il s'agit du chemin critique pour
160 // traitement des demandes
161 long targetSize =
162 maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100;
163 longue newSize = expulser (
164 . TargetSize, ResourceCache valeurs (). Itérateur ());
165 if (newSize> maxSize) {
166 // Impossible de créer un espace suffisant pour cette ressource
167 // Supprimez-la du cache
168 removeCacheEntry (path);
169 journal. warn (sm. getString ("cache.addFail", chemin));
170 }
171 }

Lors du chargement d'un webResource, le code calcule la nouvelle taille du cache. Si la taille calculée est supérieure à la taille maximale par défaut, une ou plusieurs entrées mises en cache doivent être supprimées, sinon la nouvelle taille dépassera la taille maximale. Ainsi, le code calculera un "targetSize", qui est la taille sous laquelle le cache veut rester (comme un optimum), qui est par défaut 95% du maximum. Pour atteindre cette targetSize, les entrées doivent être supprimées / expulsées du cache. Cela se fait à l'aide du code suivant:

215   expulsion longue privée  ( longue targetSize, Iterator < CachedResource > iter) { 217 long now = System. currentTimeMillis (); 219 long newSize = taille. get (); 221 while (newSize> targetSize && iter. HasNext ()) { 222 CachedResource resource = iter. suivant (); 224           // N'expire rien de ce qui a été vérifié dans le TTL 225 if (resource. GetNextCheck ()> now) { 226






continuer ;
227 }
229 // Suppression de l'entrée du cache
230 removeCacheEntry (resource. GetWebappPath ());
232 newSize = taille. get ();
233 }
235 return newSize;
236 }

Ainsi, une entrée de cache est supprimée lorsque son TTL a expiré et que targetSize n'a pas encore été atteint.

Après la tentative de libérer le cache en expulsant les entrées du cache, le code fera:

165   if (newSize> maxSize) { 
166 // Impossible de créer un espace suffisant pour cette ressource
167 // Supprimez-la du cache
168 removeCacheEntry (path);
169 journal. warn (sm. getString ("cache.addFail", chemin));
170 }

Donc, si après la tentative de libération du cache, la taille dépasse toujours le maximum, il affichera le message d'avertissement concernant l'impossibilité de libérer:

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 Le problème

Ainsi, comme l'indique le message d'avertissement, le problème est

espace libre disponible insuffisant après avoir expulsé les entrées de cache expirées - envisagez d'augmenter la taille maximale du cache

Si votre application Web charge beaucoup de ressources Web non mises en cache (environ le maximum de cache, par défaut 10 Mo) dans un court laps de temps (5 secondes), vous recevrez un avertissement.

La partie déroutante est que Tomcat 7 n'a pas montré l'avertissement. Ceci est simplement causé par ce code Tomcat 7:

1606   // Ajouter une nouvelle entrée dans le cache 
1607 synchronisé (cache) {
1608 // Vérifiez la taille du cache, et les éléments supprimer si trop gros
1609 si ((cache. Recherche (nom) == null ) && cache. Allouer (entry.size) ) {
1610 cache. charge (entrée);
1611 }
1612 }

combiné avec:

231   while (toFree> 0) { 
232 if (essais == maxAllocateIterations) {
233 // Abandonner, aucune modification n'est apportée au cache actuel
234 return false ;
235 }

Ainsi, Tomcat 7 ne génère tout simplement aucun avertissement lorsqu'il est incapable de libérer le cache, tandis que Tomcat 8 génère un avertissement.

Donc, si vous utilisez Tomcat 8 avec la même configuration de mise en cache par défaut que Tomcat 7 et que vous recevez des avertissements dans Tomcat 8, vos paramètres de mise en cache (et les miens) de Tomcat 7 fonctionnaient mal sans avertissement.

2.4 Solutions

Il existe plusieurs solutions:

  1. Augmenter le cache (recommandé)
  2. Baisser le TTL (non recommandé)
  3. Supprimer les avertissements du journal du cache (non recommandé)
  4. Désactiver le cache

2.4.1. Augmenter le cache (recommandé)

Comme décrit ici: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html

En ajoutant <Resources cacheMaxSize="XXXXX" />dans l' Contextélément in $CATALINA_BASE/conf/context.xml, où "XXXXX" représente une taille de cache accrue, spécifiée en Ko. La valeur par défaut est 10240 (10 Mo), définissez donc une taille supérieure à cela.

Vous devrez régler les paramètres optimaux. Notez que le problème peut revenir lorsque vous avez soudainement une augmentation du trafic / des demandes de ressources.

Pour éviter d'avoir à redémarrer le serveur chaque fois que vous souhaitez essayer une nouvelle taille de cache, vous pouvez la modifier sans redémarrer à l'aide de JMX.

Pour activer JMX , ajoutez ceci $CATALINA_BASE/conf/server.xmldans l' Serverélément: <Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" />et téléchargez à catalina-jmx-remote.jarpartir de https://tomcat.apache.org/download-80.cgi et placez-le dans $CATALINA_HOME/lib. Utilisez ensuite jConsole (livré par défaut avec le JDK Java) pour vous connecter via JMX au serveur et recherchez dans les paramètres les paramètres permettant d'augmenter la taille du cache pendant que le serveur est en cours d'exécution. Les modifications apportées à ces paramètres devraient prendre effet immédiatement.

2.4.2. Baisser le TTL (non recommandé)

Réduisez la cacheTtlvaleur de quelque chose de moins de 5000 millisecondes et réglez pour des paramètres optimaux.

Par exemple: <Resources cacheTtl="2000" />

Cela revient en fait à avoir et à remplir un cache en RAM sans l'utiliser.

2.4.3. Supprimer les avertissements du journal du cache (non recommandé)

Configurez la journalisation pour désactiver la journalisation org.apache.catalina.webresources.Cache.

Pour plus d'informations sur la journalisation dans Tomcat: http://tomcat.apache.org/tomcat-8.0-doc/logging.html

2.4.4. Désactiver le cache

Vous pouvez désactiver le cache en définissant cachingAllowedsur false. <Resources cachingAllowed="false" />

Bien que je puisse me souvenir que dans une version bêta de Tomcat 8, j'utilisais JMX pour désactiver le cache. (Je ne sais pas exactement pourquoi, mais il peut y avoir un problème avec la désactivation du cache via server.xml.)

Devabc
la source
Augmenter le cache? Je doute que cela fonctionne ... J'ai vu ceci: private long maxSize = 10 * 1024 * 1024; dans la source. grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/…
HoaPhan
avez-vous trouvé la réponse à pourquoi tomcat8 inonde les avertissements de cache
PHP Avenger
@HoaPhan 10 * 1024 * 1024 est un maximum de 10 Mo pour tout le cache au total. En fonction du trafic de l'application Web, celui-ci peut être atteint en quelques secondes. L'augmenter suffisamment, fonctionnera.
Devabc
@PHPAvenger Tomcat 7 n'a pas du tout averti dans cette situation, contrairement à Tomcat 8, donc cela peut être considéré comme une fonction d'avertissement. Le problème est qu'il avertit non seulement une fois, mais à chaque demande de ressource de mise en cache. Ce serait une amélioration de n'avertir qu'après un certain temps ou de mettre en cache la cible.
Devabc
@Devabc réponse impeccable! Un si classique!
gaurav
9

Vous disposez de plus de ressources statiques pour lesquelles le cache a de la place. Vous pouvez effectuer l'une des opérations suivantes:

  • Augmenter la taille du cache
  • Diminuez le TTL pour le cache
  • Désactiver la mise en cache

Pour plus de détails, consultez la documentation de ces options de configuration.

Mark Thomas
la source
1
Merci pour le commentaire. Je comprends la signification de l'exception, et bien sûr j'ai lu la documentation à laquelle vous avez lié, mais je ne comprends pas pourquoi cela passerait de 7 à 8 sans changement de configuration. C'est pourquoi le gestionnaire de ressources du système de fichiers par défaut serait différent de 8 à 7, sans référence à aucun changement, et il est suspect qu'un bogue de démarrage ait été signalé et supposément corrigé.
iainmac999
1
Peut-être que si vous aviez lu le guide de migration - en particulier tomcat.apache.org/migration-8.html#Web_application_resources - les choses seraient plus claires.
Mark Thomas
Cela aiderait si la documentation faisait un peu plus pour a) expliquer quelles ressources vont dans ce cache et pourquoi (beaucoup de malentendus abondent à ce sujet!) Et b) quel impact différents paramètres peuvent avoir (par exemple, simplement en créant aveuglément le paramètre de cache de chaque application Web assez grande peut manger une tonne de mémoire) et comment régler cela correctement. Cela aiderait également s'il y avait une distinction dans le code et la configuration entre la mise en cache des ressources statiques utilisées par l'application elle-même et les fichiers statiques demandés par les agents utilisateurs et simplement fournis par l'application.
volkerk le
4

Ce n'est pas une solution dans le sens où cela ne résout pas les conditions qui font apparaître le message dans les journaux, mais le message peut être supprimé en ajoutant ce qui suit à conf/logging.properties:

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

Cela filtre les journaux «Impossible d'ajouter la ressource», qui sont au niveau AVERTISSEMENT.

À mon avis, un WARNINGn'est pas nécessairement une erreur qui doit être corrigée, mais peut plutôt être ignorée si on le souhaite.

Booth Geoffrey
la source
8
Haha. cela ne résout pas le problème. Cela ne le montre tout simplement pas. WTF!
T3rm1
Cela résout le problème de la journalisation excessive, qui peut être un problème important en soi. Cela revient au comportement des versions antérieures de Tomcat, où les choses fonctionnaient suffisamment bien pour beaucoup, donc en ce sens, cela «résout» le problème. Cela ne résout pas le problème du réglage du cache tomcat, que la réponse de devabc couvre très bien.
volkerk le