Как и в случае любой проблемы с управлением памятью, это длинная история, так что запутайтесь.
У нас есть приложение, которое страдает от некоторых проблем управления памятью, поэтому я пытался профилировать приложение, чтобы понять, в чем проблема. Сегодня я видел эту тему сегодня:
Исключение из сеанса Tomcat для предотвращения ошибки OutOfMemoryEr
... что похоже на то, что я видел в профилировщике. По сути, если бы я ударил приложение с группой пользователей с помощью Jmeter, оно бы долго удерживало память в куче, в конце концов, пока сессии не начали истекать. Однако, в отличие от плаката в этой теме, у меня есть источник и возможность попробовать реализовать сеансы постоянного состояния с Tomcat, что я и пытался сделать сегодня, с ограниченным успехом. Я думаю, что это некоторые настройки конфигурации, которые мне не хватает. Вот что у меня есть в context.xml:
<Manager className='org.apache.catalina.session.PersistentManager'
saveOnRestart='false'
maxActiveSessions='5'
minIdelSwap='0'
maxIdleSwap='1'
maxInactiveInterval='600'
maxIdleBackup='0'>
<Store className='org.apache.catalina.session.FileStore'/>
</Manager>
И в web.xml у меня есть это:
<session-config>
<session-timeout>
10
</session-timeout>
</session-config>
В идеале, я бы хотел, чтобы сеансы отключались через час, но для целей тестирования это нормально. Теперь, поиграв с некоторыми вещами и, наконец, перейдя к этим настройкам, я наблюдаю за приложением в профилировщике, и вот что я вижу:
![enter image description here](https://i.stack.imgur.com/6BIL3.jpg)
Как вы можете видеть на картинке, я поместил некоторые аннотации. Это часть, обведенная вокруг вопросительного знака, которую я действительно не понимаю больше всего на свете. Вы можете видеть, что я использую кнопку «Выполнить сборку» на Jconsole в нескольких разных точках, и вы можете увидеть часть диаграммы, где я запускаю приложение со многими клиентами с Jmeter.
Если я правильно помню (мне нужно было бы вернуться и действительно задокументировать это, чтобы быть уверенным), до того, как я реализовал постоянное состояние, кнопка GC не сделала бы почти ничего в отношении очистки кучи. Странный момент здесь в том, что мне кажется, что я должен вручную запустить GC для этого постоянного состояния, чтобы действительно помочь с чем-либо.
Или это простой сценарий утечки памяти? Ранее сегодня я взял дамп кучи и загрузил его в инструмент Eclipse Memory Analyzer, использовал функцию «Обнаружение утечки», и все, что он сделал, это подтвердил теорию о том, что это проблема размера сеанса; единственная обнаруженная утечка была в java.util.concurrent.ConcurrentHashMap $ Segment, которая привела меня к этой теме Память, полностью используемая Java ConcurrentHashMap (под Tomcat)
, что заставляет меня думать, что это не приложение, которое на самом деле утечка.
Другие соответствующие данные:
- Запуск / тестирование этого на моей локальной машине в настоящее время. Вот откуда все эти результаты.
- Использование Tomcat 6
- Это приложение JSF2.0
- Я добавил системное свойство -Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE = true согласно документации Tomcat
Итак, я думаю, здесь есть несколько вопросов:
1. Я правильно настроил?
2. Есть ли утечка памяти?
3. Что происходит в этом профиле памяти?
4. Это (относительно) нормально?
Заранее спасибо.
UPDATE
Итак, я попробовал советы Шона и нашел несколько новых интересных вещей.
Слушатель сеанса отлично работает и сыграл важную роль в анализе этого сценария. Что-то еще, что я забыл упомянуть, это то, что загрузка приложения действительно ограничена одной страницей, которая почти функционально усложняется. Таким образом, при тестировании я иногда стремлюсь попасть на эту страницу, а иногда я избегаю ее. Итак, в моем следующем раунде тестов, на этот раз с использованием слушателя сеанса, я обнаружил следующее:
1) Поразите приложение несколькими десятками клиентов, просто посетив простую страницу. Я отметил, что все сеансы были освобождены, как и ожидалось, после указанного ограничения по времени, и память была освобождена. Та же самая вещь отлично работает с тривиальным числом клиентов, для сложного случая, попав на «большую» страницу.
2) Затем я попытался запустить приложение со сложным сценарием использования с несколькими десятками клиентов. На этот раз было начато на несколько десятков больше сеансов, чем ожидалось. Казалось, что каждый клиент инициировал от одного до трех сеансов. По истечении времени истечения сеанса освободилось немного памяти, но, по словам слушателя сеанса, только около трети сеансов было уничтожено. Несмотря на это, папка, которая на самом деле содержит данные сессий, пуста. Большая часть памяти, которая была использована, также сохраняется. Но после ровно одного часа работы стресс-теста сборщик мусора запускается, и все возвращается в нормальное состояние.
Итак, дополнительные вопросы включают в себя:
1) Почему сеансы могут обрабатываться должным образом в простом случае, но когда вещи становятся интенсивными, они перестают правильно управляться? Обработчик сеанса искажает информацию, или JMeter как-то влияет на это?
2) Почему сборщик мусора ждет один час, чтобы запустить? Существует ли системный параметр, который требует, чтобы сборщик мусора ДОЛЖЕН работать в течение определенного периода времени, или если какой-то параметр конфигурации мне не хватает?
Еще раз спасибо за постоянную поддержку.
ОБНОВЛЕНИЕ 2
Просто небольшое замечание: поэкспериментируя с этим, я обнаружил, что причина получения разных отчетов о количестве живых сессий связана с тем, что я использую постоянную сессию; если я выключу, все работает как положено. На странице Tomcat для постоянного сеанса действительно говорится, что это экспериментальная функция. Должно быть, это вызов событий сеанса, которые слушатель воспринимает, когда нетипично ожидать, что он это сделает.