У мене виникло таке ж питання при модернізації з 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 Рішення
Є кілька рішень:
- Збільшити кеш (рекомендується)
- Опустіть 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.)