Tive o mesmo problema ao atualizar do Tomcat 7 para o 8: uma grande inundação contínua de avisos de log sobre o cache.
1. Resposta curta
Adicione-o ao Context
elemento xml do seu $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" />
Portanto, o padrão é 10240
(10 mbyte), então defina um tamanho maior do que isso. Em seguida, ajuste as configurações ideais onde os avisos desaparecem. Observe que os avisos podem voltar em situações de tráfego intenso.
1.1 A causa (breve explicação)
O problema é causado pelo fato de o Tomcat não conseguir atingir seu tamanho de cache de destino devido às entradas de cache que são menores que o TTL dessas entradas. Portanto, o Tomcat não tinha entradas de cache suficientes para que pudesse expirar, porque eram muito recentes, de modo que não poderia liberar cache suficiente e, portanto, gera avisos.
O problema não apareceu no Tomcat 7 porque o Tomcat 7 simplesmente não emitia avisos nessa situação. (Fazendo você e eu usarmos configurações de cache insatisfatórias sem sermos notificados.)
O problema aparece ao receber uma quantidade relativamente grande de solicitações HTTP para recursos (geralmente estáticos) em um período de tempo relativamente curto em comparação com o tamanho e o TTL do cache. Se o cache estiver atingindo seu máximo (10 MB por padrão) com mais de 95% de seu tamanho com novas entradas de cache (novo significa menos de 5 segundos no cache), você receberá uma mensagem de aviso para cada recurso da web que o Tomcat tenta para carregar no cache.
1.2 Informação opcional
Use JMX se precisar ajustar cacheMaxSize em um servidor em execução sem reiniciá-lo.
A correção mais rápida seria desabilitar completamente o cache <Resources cachingAllowed="false" />
:, mas isso está abaixo do ideal, então aumente cacheMaxSize como acabei de descrever.
2. Resposta longa
2.1 Informações básicas
Um WebSource é um arquivo ou diretório em um aplicativo da web. Por motivos de desempenho, o Tomcat pode armazenar WebSources em cache. O máximo do cache de recursos estáticos (todos os recursos no total) é, por padrão, 10240 kbyte (10 mbyte). Um webResource é carregado no cache quando o webResource é solicitado (por exemplo, ao carregar uma imagem estática) e é então chamado de entrada de cache. Cada entrada de cache possui um TTL (tempo de vida), que é o tempo que a entrada de cache pode permanecer no cache. Quando o TTL expira, a entrada do cache é elegível para ser removida do cache. O valor padrão do cacheTTL é 5000 milissegundos (5 segundos).
Há mais informações sobre o cache, mas isso é irrelevante para o problema.
2.2 A causa
O código a seguir da classe Cache mostra a política de cache em detalhes:
152 // O conteúdo não será armazenado em cache, mas ainda precisamos do tamanho dos metadados
153 long delta = cacheEntry. getSize (); Tamanho
154 . addAndGet (delta);
156 if (size. Get ()> maxSize) {
157 // Processar recursos não ordenados para velocidade. Trades cache
158 // eficiência (entradas mais novas podem ser removidas antes das
159 // mais antigas ) para velocidade, uma vez que este é o caminho crítico para
160 // processamento de solicitação
161 long targetSize =
162 maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100;
163 longo newSize = despejar (
164 . TargetSize, resourceCache valores (). Iteração ());
165 if (newSize> maxSize) {
166 // Não é possível criar espaço suficiente para este recurso
167 // Remova-o do cache
168 removeCacheEntry (path);
169 log. warn (sm. getString ("cache.addFail", caminho));
170 }
171 }
Ao carregar um webResource, o código calcula o novo tamanho do cache. Se o tamanho calculado for maior do que o tamanho máximo padrão, uma ou mais entradas em cache devem ser removidas, caso contrário, o novo tamanho excederá o máximo. Assim, o código calculará um "targetSize", que é o tamanho que o cache deseja manter (como ideal), que é por padrão 95% do máximo. Para alcançar este targetSize, as entradas devem ser removidas / removidas do cache. Isso é feito usando o seguinte código:
215 despejo longo privado ( long targetSize, Iterator < CachedResource > iter) { 217 long now = System. currentTimeMillis (); 219 longo newSize = size. get (); 221 while (newSize> targetSize && iter. HasNext ()) { 222 CachedResource resource = iter. próximo (); 224 // Não expira nada que foi verificado no TTL 225 if (resource. GetNextCheck ()> now) { 226
continue ;
227 }
229 // Remova a entrada do cache
230 removeCacheEntry (resource. GetWebappPath ());
232 newSize = size. get ();
233 }
235 retornar novoTamanho;
236 }
Portanto, uma entrada de cache é removida quando seu TTL expira e o targetSize ainda não foi alcançado.
Após a tentativa de liberar o cache removendo as entradas do cache, o código fará:
165 if (newSize> maxSize) {
166 // Não é possível criar espaço suficiente para este recurso
167 // Remova-o do cache
168 removeCacheEntry (path);
169 log. warn (sm. getString ("cache.addFail", caminho));
170 }
Portanto, se após a tentativa de liberar o cache, o tamanho ainda ultrapassar o máximo, será exibida a mensagem de aviso sobre a impossibilidade de 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 O problema
Como diz a mensagem de aviso, o problema é
espaço livre insuficiente disponível após a remoção de entradas de cache expiradas - considere aumentar o tamanho máximo do cache
Se o seu aplicativo da web carregar muitos webResources não armazenados em cache (no máximo de cache, por padrão 10 MB) em um curto período (5 segundos), você receberá o aviso.
A parte confusa é que o Tomcat 7 não mostrou o aviso. Isso é causado simplesmente por este código Tomcat 7:
1606 // Adicionar nova entrada ao cache
1607 synchronized (cache) {
1608 // Verificar o tamanho do cache e remover elementos se forem muito grandes
1609 if ((cache. Lookup (name) == null ) && cache. Alocar (entry.size) ) {
1610 cache. carregar (entrada);
1611 }
1612 }
combinado com:
231 while (toFree> 0) {
232 if (tentativas == maxAllocateIterations) {
233 // Desista, nenhuma mudança é feita no cache atual
234 return false ;
235 }
Portanto, o Tomcat 7 simplesmente não exibe nenhum aviso quando não consegue liberar o cache, enquanto o Tomcat 8 exibe um aviso.
Portanto, se você estiver usando o Tomcat 8 com a mesma configuração de cache padrão do Tomcat 7 e recebeu avisos no Tomcat 8, então suas (e minhas) configurações de cache do Tomcat 7 estavam funcionando mal sem aviso.
2.4 Soluções
Existem várias soluções:
- Aumentar o cache (recomendado)
- Diminua o TTL (não recomendado)
- Suprimir avisos de log de cache (não recomendado)
- Desativar cache
2.4.1. Aumentar o cache (recomendado)
Conforme descrito aqui: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html
Adicionando <Resources cacheMaxSize="XXXXX" />
dentro do Context
elemento em $CATALINA_BASE/conf/context.xml
, onde "XXXXX" representa um tamanho de cache aumentado, especificado em kbytes. O padrão é 10240 (10 mbyte), então defina um tamanho maior do que isso.
Você terá que ajustar para configurações ideais. Observe que o problema pode voltar quando, de repente, houver um aumento nas solicitações de tráfego / recursos.
Para evitar ter que reiniciar o servidor toda vez que você quiser tentar um novo tamanho de cache, você pode alterá-lo sem reiniciar usando JMX.
Para habilitar JMX , adicionar isso para $CATALINA_BASE/conf/server.xml
dentro do Server
elemento:
<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" />
e descarga catalina-jmx-remote.jar
de https://tomcat.apache.org/download-80.cgi e colocá-lo em $CATALINA_HOME/lib
. Em seguida, use o jConsole (fornecido por padrão com o Java JDK) para se conectar por JMX ao servidor e verifique as configurações para aumentar o tamanho do cache enquanto o servidor está em execução. As alterações nessas configurações devem entrar em vigor imediatamente.
2.4.2. Diminua o TTL (não recomendado)
Diminua o cacheTtl
valor em um valor inferior a 5000 milissegundos e ajuste para obter as configurações ideais.
Por exemplo: <Resources cacheTtl="2000" />
Isso se resume a ter e preencher um cache na memória RAM sem usá-lo.
2.4.3. Suprimir avisos de log de cache (não recomendado)
Configure o log para desabilitar o logger org.apache.catalina.webresources.Cache
.
Para obter mais informações sobre como fazer login no Tomcat: http://tomcat.apache.org/tomcat-8.0-doc/logging.html
2.4.4. Desativar cache
Você pode desativar o cache configurando cachingAllowed
para false
.
<Resources cachingAllowed="false" />
Embora eu possa me lembrar que em uma versão beta do Tomcat 8, eu estava usando JMX para desabilitar o cache. (Não sei exatamente por que, mas pode haver um problema com a desativação do cache via server.xml.)