Закидання Tomcat 8 - 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


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


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 на запущеному сервері, не перезавантажуючи його.

Найшвидшим виправленням було б повністю відключити кеш:, <Resources cachingAllowed="false" />але це неоптимально, тому збільште cacheMaxSize, як я щойно описав.

2. Довга відповідь

2.1 Довідкова інформація

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

Про кешування можна сказати більше, але це не має значення для проблеми.

2.2 Причина

Наступний код класу Кеш детально показує політику кешування:

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 deleteCacheEntry (шлях);
169 журнал. попереджати (см. getString ("cache.addFail", шлях));
170 }
171 }

Під час завантаження веб-ресурсу код обчислює новий розмір кешу. Якщо обчислений розмір більший, ніж максимальний розмір за замовчуванням, слід вилучити одну або більше кешованих записів, інакше новий розмір перевищить максимальний. Таким чином, код обчислить "targetSize", який є розміром, в якому кеш хоче залишитись (як оптимальний), який за замовчуванням становить 95% від максимального. Щоб досягти цього targetSize, записи потрібно видалити / вилучити з кешу. Це робиться за допомогою наступного коду:

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

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

Після спроби звільнити кеш, вилучивши записи кеша, код виконає:

165   if (newSize> maxSize) { 
166 // Неможливо створити достатній простір для цього ресурсу
167 // Видалити його з кешу
168 deleteCacheEntry (шлях);
169 журнал. попереджати (см. getString ("cache.addFail", шлях));
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 (спроби == maxAllocateIterations) {
233 // Відмовитись , зміни в поточному кеші
234 повернення помилкові не вносяться ;
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.)


Збільшити кеш? Я сумніваюся, що це спрацює ... Я бачив це: приватний довгий 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.