У меня была такая же проблема при обновлении с 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 Решения
Есть несколько решений:
- Увеличить кеш (рекомендуется)
- Понизьте TTL (не рекомендуется)
- Отключить предупреждения журнала кеширования (не рекомендуется)
- Отключить кеш
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.)