Tomcat 8 throwing - org.apache.catalina.webresources.Cache.getResource Невозможно добавить ресурс

111

Я только что обновил Tomcat с версии 7.0.52 до 8.0.14.

Я получаю это для множества файлов статических изображений:

org.apache.catalina.webresources.Cache.getResource Невозможно добавить ресурс по адресу [/base/1325/WA6144-150x112.jpg] в кеш, так как после удаления просроченных записей кеша было недостаточно свободного места - рассмотрите возможность увеличения максимального размера кеша

Я не указал никаких конкретных настроек ресурса, и я не получил этого для 7.0.52.

Я нашел упоминание об этом при запуске в отчете об ошибке, который предположительно был исправлен. Для меня это происходит не при запуске, а постоянно при запросе ресурса.

У кого-нибудь еще есть эта проблема?

Пытаюсь хотя бы просто отключить кеш, но не могу найти пример того, как указать не использовать кеш. Атрибуты ушли из контекста в Tomcat версии 8. Попробовали добавить ресурс, но не смогли правильно настроить конфигурацию.

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

Спасибо.

iainmac999
источник
Нет ответов - наверное, я единственный, у кого возникла эта проблема.
iainmac999
2
Решение здесь: serverfault.com/questions/644415/…
Дмитрий
1
Что касается отсутствующего атрибута в контексте Tomcat 8, вот выдержка из руководства по миграции (выделено мной): « Реорганизация ресурсов также привела к удалению ряда атрибутов из реализации контекста по умолчанию (org.apache.catalina.core .StandardContext). Следующие атрибуты теперь можно настроить с помощью реализации ресурсов, используемых веб-приложением ". Подробнее в соответствующем руководстве по миграции .
informatik01
@ iainmac999, так и не выбрав правильный ответ за 2 года, мы можем согласиться, что это работает в обоих направлениях?
davidjmcclelland

Ответы:

161

В вашем $CATALINA_BASE/conf/context.xmlблоке добавления ниже перед</Context>

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

Для получения дополнительной информации: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html

Destroyica
источник
11
Отдельные читатели, вероятно, захотят изменить значение cacheMaxSize на значение менее 100 мегабайт.
Эрик Шпигельберг,
до сих пор сообщение об ошибке наводняло мои журналы консоли. Теперь все ясно. Спасибо
Abubacker Siddik
152

У меня была такая же проблема при обновлении с Tomcat 7 до 8: непрерывный большой поток предупреждений журнала о кешировании.

1. Краткий ответ

Добавьте это в Contextэлемент xml вашего $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" />

Таким образом, по умолчанию 10240(10 мегабайт), поэтому установите размер больше, чем это. Затем настройте оптимальные настройки, при которых предупреждения исчезают. Обратите внимание, что предупреждения могут появиться снова при повышенном трафике.

1.1 Причина (краткое объяснение)

Проблема вызвана тем, что Tomcat не может достичь своего целевого размера кэша из-за записей кеша, которые меньше TTL этих записей. Таким образом, у Tomcat не было достаточно записей в кеше, срок действия которых мог истечь, потому что они были слишком свежими, поэтому он не мог освободить достаточно кеша и, таким образом, выводил предупреждения.

Проблема не возникла в Tomcat 7, потому что Tomcat 7 просто не выводил предупреждения в этой ситуации. (Заставляет нас с вами использовать плохие настройки кеша без уведомления.)

Проблема возникает при получении относительно большого количества HTTP-запросов на ресурсы (обычно статических) за относительно короткий период времени по сравнению с размером и TTL кеша. Если кеш достигает своего максимума (по умолчанию 10 МБ) с более чем 95% своего размера со свежими записями в кеше (свежие означает менее 5 секунд в кеше), вы получите предупреждающее сообщение для каждого веб-ресурса, который пытается Tomcat. загрузить в кеш.

1.2 Дополнительная информация

Используйте JMX, если вам нужно настроить cacheMaxSize на работающем сервере без его перезагрузки.

Самым быстрым решением будет полное отключение cache : <Resources cachingAllowed="false" />, но это неоптимально, поэтому увеличьте cacheMaxSize, как я только что описал.

2. Длинный ответ

2.1 Справочная информация

WebSource файл или каталог в веб - приложении. По соображениям производительности Tomcat может кэшировать веб-источники. Максимум кэш статического ресурса (все ресурсы в целом) является по умолчанию 10240 кбайт (10 мегабайт). WebResource загружается в кеш, когда запрашивается webResource (например, при загрузке статического изображения), затем он называется записью кеша. Каждая запись кэша имеет TTL (время жизни), то есть время, в течение которого записи кэша разрешено оставаться в кэше. Когда TTL истекает, запись кэша может быть удалена из кеша. Значение cacheTTL по умолчанию составляет 5000 миллисекунд (5 секунд).

О кешировании можно сказать больше, но это не имеет отношения к проблеме.

2.2 Причина

Следующий код из класса Cache подробно показывает политику кэширования:

152   // Контент не будет кэшироваться, но нам все еще нужен размер метаданных 
153 long delta = cacheEntry. getSize ();
154 размер. addAndGet (дельта);
156 if (size. Get ()> maxSize) {
157 // Обработка ресурсов неупорядоченно по скорости. Кэш сделок
158 // эффективность (более молодые записи могут быть исключены перед старыми
159 //) для скорости, поскольку это критический путь для
160 // обработки запроса
161 long targetSize =
162 maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100;
163 длиной NewSize = выселить (
164 . TargetSize, resourceCache значения (). Итератор ());
165 if (newSize> maxSize) {
166 // Невозможно создать достаточно места для этого ресурса
167 // Удалить его из кеша
168 removeCacheEntry (path);
169 лог. warn (см. getString ("cache.addFail", path));
170 }
171 }

При загрузке webResource код вычисляет новый размер кеша. Если рассчитанный размер больше максимального размера по умолчанию, необходимо удалить одну или несколько кэшированных записей, иначе новый размер превысит максимальный. Таким образом, код вычислит "targetSize", который представляет собой размер, при котором кэш хочет оставаться в пределах (как оптимальный), который по умолчанию составляет 95% от максимума. Для достижения этого targetSize записи должны быть удалены / исключены из кеша. Это делается с помощью следующего кода:

215   частное  долгое выселение ( long targetSize, Iterator < CachedResource > iter) { 
217 long now = System. currentTimeMillis ();
219 long newSize = размер. получить ();
221 while (newSize> targetSize && iter. HasNext ()) {
222 CachedResource resource = iter. следующий ();
224 // Не истекает срок действия всего, что было проверено в пределах TTL
225 if (resource. GetNextCheck ()> now) {
226 продолжить ;
227 }
229 // Удаляем запись из кеша
230 removeCacheEntry (resource. GetWebappPath ());
232 newSize = размер. получить ();
233 }
235 return newSize;
236 }

Таким образом, запись в кеше удаляется, когда истекает ее TTL, а targetSize еще не достигнут.

После попытки освободить кеш путем удаления записей из кеша код выполнит следующее:

165   if (newSize> maxSize) { 
166 // Невозможно создать достаточно места для этого ресурса
167 // Удалить его из кеша
168 removeCacheEntry (path);
169 лог. warn (см. getString ("cache.addFail", path));
170 }

Поэтому, если после попытки освободить кеш, размер по-прежнему превышает максимальный, будет показано предупреждающее сообщение о невозможности освободить:

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 Проблема

Итак, как говорится в предупреждающем сообщении, проблема в

недостаточно свободного места после удаления просроченных записей кеша - рассмотрите возможность увеличения максимального размера кеша

Если ваше веб-приложение загружает много некэшированных веб-ресурсов (около максимального размера кеша, по умолчанию 10 МБ) в течение короткого времени (5 секунд), вы получите предупреждение.

Заблуждение заключается в том, что Tomcat 7 не отображал предупреждения. Это просто вызвано этим кодом Tomcat 7:

1606   // Добавить новую запись в кэш 
1607 синхронизируется (кэш) {
1608 // Проверка размера кэша и удаления элементов , если слишком большой
1609 , если ((кэш. Поиск (имя) == NULL ) && кэш. Выделения (entry.size) ) {
1610 кеш. загрузка (запись);
1611 }
1612 }

в сочетании с:

231   while (toFree> 0) { 
232 if (plays == maxAllocateIterations) {
233 // Сдаваться, в текущий кеш не вносятся изменения
234 return false ;
235 }

Таким образом, Tomcat 7 просто не выводит никаких предупреждений, когда не может освободить кеш, тогда как Tomcat 8 выводит предупреждение.

Итак, если вы используете Tomcat 8 с той же конфигурацией кэширования по умолчанию, что и Tomcat 7, и вы получили предупреждения в Tomcat 8, то ваши (и мои) настройки кэширования Tomcat 7 работали плохо без предупреждения.

2.4 Решения

Есть несколько решений:

  1. Увеличить кеш (рекомендуется)
  2. Понизьте TTL (не рекомендуется)
  3. Отключить предупреждения журнала кеширования (не рекомендуется)
  4. Отключить кеш

2.4.1. Увеличить кеш (рекомендуется)

Как описано здесь: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html

Путем добавления <Resources cacheMaxSize="XXXXX" />внутри Contextэлемента в $CATALINA_BASE/conf/context.xml, где «XXXXX» означает увеличенный размер кэша, указанный в килобайтах. По умолчанию 10240 (10 мегабайт), поэтому установите размер больше этого.

Вам нужно будет настроить оптимальные настройки. Обратите внимание, что проблема может вернуться, когда у вас внезапно увеличится количество запросов трафика / ресурсов.

Чтобы избежать перезагрузки сервера каждый раз, когда вы хотите попробовать новый размер кеша, вы можете изменить его без перезапуска с помощью JMX.

Чтобы включить JMX , добавьте это $CATALINA_BASE/conf/server.xmlв Serverэлемент:, <Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" />загрузите catalina-jmx-remote.jarс https://tomcat.apache.org/download-80.cgi и вставьте $CATALINA_HOME/lib. Затем используйте jConsole (поставляется по умолчанию с Java JDK) для подключения через JMX к серверу и просмотрите настройки для увеличения размера кеша во время работы сервера. Изменения в этих настройках должны немедленно вступить в силу.

2.4.2. Понизьте TTL (не рекомендуется)

Уменьшите cacheTtlзначение менее чем на 5000 миллисекунд и настройтесь на оптимальные настройки.

Например: <Resources cacheTtl="2000" />

Фактически это сводится к тому, что кэш в оперативной памяти заполняется без его использования.

2.4.3. Отключить предупреждения журнала кеширования (не рекомендуется)

Настройте ведение журнала, чтобы отключить средство ведения журнала для org.apache.catalina.webresources.Cache.

Для получения дополнительной информации о входе в Tomcat: http://tomcat.apache.org/tomcat-8.0-doc/logging.html

2.4.4. Отключить кеш

Вы можете отключить кеш, установив cachingAllowedзначение false. <Resources cachingAllowed="false" />

Хотя я помню, что в бета-версии Tomcat 8 я использовал JMX для отключения кеша. (Не знаю, почему именно, но может возникнуть проблема с отключением кеша через server.xml.)

Devabc
источник
Увеличить кеш? Сомневаюсь, что это сработает ... Я видел это: private long maxSize = 10 * 1024 * 1024; в источнике. grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/…
HoaPhan
Вы нашли ответ на вопрос, почему tomcat8 наводит предупреждения о переполнении кеша
PHP Avenger
@HoaPhan 10 * 1024 * 1024 - это максимум 10 МБ для всего кеша. В зависимости от трафика веб-приложения это может быть достигнуто за секунды. Увеличив его достаточно далеко, будет работать.
Devabc
@PHPAvenger Tomcat 7 вообще не предупреждал в этой ситуации, тогда как Tomcat 8 предупреждает, поэтому это можно рассматривать как функцию предупреждения. Проблема в том, что он предупреждает не один раз, а при каждом запросе ресурса кэширования. Было бы лучше, если бы вы получали предупреждение только по прошествии определенного времени или попадания в цель кеширования.
Devabc
@Devabc безупречный ответ! ТАК классика!
gaurav
9

У вас есть больше статических ресурсов, для которых есть место в кеше. Вы можете сделать одно из следующего:

  • Увеличить размер кеша
  • Уменьшите TTL для кеша
  • Отключить кеширование

Дополнительные сведения см. В документации по этим параметрам конфигурации.

Марк Томас
источник
1
Спасибо за комментарий. Я понимаю значение исключения и, конечно же, читал документацию, на которую вы ссылались, однако я не понимаю, почему это изменится с 7 на 8 без изменений конфигурации. То есть, почему обработчик ресурсов файловой системы по умолчанию должен отличаться от 8 до 7, без ссылки на какие-либо изменения, и подозрительно, что ошибка запуска была сообщена и предположительно исправлена.
iainmac999
1
Возможно, если бы вы читали руководство по миграции, в частности tomcat.apache.org/migration-8.html#Web_application_resources, все было бы яснее.
Марк Томас
Было бы полезно, если бы в документации было немного больше: а) объяснения того, какие ресурсы входят в этот кеш и почему (много недоразумений по этому поводу!) И б) какое влияние могут иметь различные настройки (например, просто слепое создание настроек кеша каждого веб-приложения довольно большой может съесть тонну памяти) и как это правильно настроить. Также было бы полезно, если бы было различие в коде и конфигурации между кэшированием статических ресурсов, используемых самим приложением, и статических файлов, запрашиваемых пользовательскими агентами и просто доставляемых приложением.
volkerk
4

Это не решение в том смысле, что оно не устраняет условия, вызывающие появление сообщения в журналах, но сообщение можно подавить, добавив следующее к conf/logging.properties:

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

Это отфильтровывает журналы «Невозможно добавить ресурс», которые находятся на уровне ПРЕДУПРЕЖДЕНИЕ.

На мой взгляд, a WARNING- это не обязательно ошибка, которую необходимо устранить, но при желании ее можно игнорировать.

Джеффри Бут
источник
8
Ха - ха. это не решает проблемы. Он просто этого не показывает. WTF!
T3rm1
Это решает проблему чрезмерного ведения журнала, которое само по себе может стать серьезной проблемой. Он возвращается к поведению предыдущих версий tomcat, где у многих все работало достаточно хорошо, так что в этом смысле он «решает» проблему. Он не решает проблему фактической настройки кеша tomcat, что очень хорошо покрывает ответ devabc.
volkerk