JRun поток конфигурации

Я и моя команда изо всех сил пытались сохранить кластерное приложение ColdFusion стабильным в течение большей части последних 6 месяцев с небольшим результатом. Мы обращаемся к SF в надежде на то, что кто-нибудь найдет экспертов по JRun или свежие идеи, потому что мы не можем понять это.

Настройка:
Два экземпляра ColdFusion 7.0.2, сгруппированные с JRun 4 (с последним обновлением) на IIS 6 под Windows Server 2003. Два четырехъядерных процессора, 8 ГБ ОЗУ.

Проблема:
Время от времени, обычно один раз в неделю, один из экземпляров полностью прекращает обработку запроса. Там нет никакой активности, и мы должны перезапустить ее.

Что мы знаем:
Каждый раз, когда это происходит, журнал ошибок JRun всегда полон java.lang.OutOfMemoryError: невозможно создать новый собственный поток.

После прочтения документации по JRun из Macromedia/Adobe и множества запутанных постов в блоге мы более или менее сузили ее до неправильных / неоптимизированных настроек пула потоков JRun в экземпляре jrun.xml.

Соответствующая часть нашего jrun.xml:

<service class="jrun.servlet.jrpp.JRunProxyService" name="ProxyService">
    <attribute name="activeHandlerThreads">500</attribute>
    <attribute name="backlog">500</attribute>
    <attribute name="deactivated">false</attribute>
    <attribute name="interface">*</attribute>
    <attribute name="maxHandlerThreads">1000</attribute>
    <attribute name="minHandlerThreads">1</attribute>
    <attribute name="port">51003</attribute>
    <attribute name="threadWaitTimeout">300</attribute>
    <attribute name="timeout">300</attribute>
{snip}  
</service>

На прошлой неделе я включил ведение журнала метрик JRun для сбора данных, связанных с потоками. Это сводка данных после записи в журнал в течение недели.

Средние значения:

{jrpp.listenTh}       1
{jrpp.idleTh}         9
{jrpp.delayTh}        0
{jrpp.busyTh}         0
{jrpp.totalTh}       10
{jrpp.delayRq}        0
{jrpp.droppedRq}      0
{jrpp.handledRq}      4
{jrpp.handledMs}   6036
{jrpp.delayMs}        0
{freeMemory}      48667
{totalMemory}    403598
{sessions}          737
{sessionsInMem}     737

Максимальные значения:

{jrpp.listenTh}       10
{jrpp.idleTh}         94
{jrpp.delayTh}         1
{jrpp.busyTh}         39
{jrpp.totalTh}       100
{jrpp.delayRq}         0
{jrpp.droppedRq}       0
{jrpp.handledRq}      87
{jrpp.handledMs}  508845
{jrpp.delayMs}         0
{freeMemory}      169313
{totalMemory}     578432
{sessions}          2297
{sessionsInMem}     2297

Есть идеи о том, что мы можем попробовать сейчас?

Ура!


РЕДАКТИРОВАТЬ #1 -> Вещи, которые я забыл упомянуть: Windows Server 2003 Enterprise с JVM 1.4.2 (для JRun)

Максимальный размер кучи составляет около 1,4 ГБ, да. Раньше у нас были утечки, но мы их исправили, теперь приложение использует около 400 МБ, редко больше. Максимальный размер кучи установлен в 1200 МБ, поэтому мы не достигаем его. Когда у нас были утечки, JVM просто взорвалась, и экземпляр перезапустился сам. Сейчас этого не происходит, просто прекращается обработка входящего запроса.

Мы думали, что это связано с темой, следующей за этим сообщением в блоге: http://www.talkingtree.com/blog/index.cfm/2005/3/11/NewNativeThread

Выдаваемое исключение Java относится к типу OutOfMemory, но на самом деле оно не говорит о том, что у нас закончилось пространство кучи, просто оно не может создавать новые потоки. Тип исключения немного вводит в заблуждение.

В основном блог говорит, что 500 как activeHandlerThreads может быть слишком высоким, но мои метрики, кажется, показывают, что мы не достигли того, что сбивает нас с толку.

2 ответа

Решение

Что ж, давайте рассмотрим некоторые большие проблемы с изображением, прежде чем углубляться в детали конфигурации JRun.

Если вы получаете исключения java.lang.OutOfMemoryError в журнале ошибок JRun, значит, у вас недостаточно памяти. Никаких возражений за это, пожалуйста;-). Вы не сказали, используете ли вы 32- или 64-разрядную версию Windows, но вы сказали, что у вас 8 ГБ ОЗУ, так что это повлияет на ответ. Независимо от того, используете ли вы 32- или 64-разрядную JVM (и какую версию), это также повлияет на ситуацию. Так что это несколько ответов, которые помогут нам разобраться в этом.

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

  1. У вашего приложения течет память. На некоторые объекты, которые использует ваше приложение, постоянно ссылаются, и поэтому они никогда не могут быть использованы для сборки мусора; или еще хуже - какой-то объект, созданный новым при каждом запросе, постоянно ссылается на другой объект и, следовательно, никогда не может быть использован для сборки мусора. Корректная обработка сеанса J2EE может быть особенно сложной в этом отношении.
  2. Объем необходимой памяти для обработки каждого одновременного запроса (на настроенном уровне одновременного запроса) превышает объем памяти, доступный в куче JVM. Например, у вас есть размер кучи 1 ГБ, и каждый запрос может использовать до 10 МБ. Ваш сервер приложений настроен на 150 одновременных запросов. (Упрощенные числа, я знаю). В этом случае вам определенно не хватит памяти, если вы столкнулись с 100 или более одновременными запросами под нагрузкой (если каждый запрос использовал максимальный объем памяти, необходимый для выполнения запроса).

Другие вещи, которые следует иметь в виду: в 32-битной Windows 32-битная JVM может выделить только приблизительно 1,4 ГБ памяти. Я не припоминаю, если 32-битная JVM в 64-битной Windows имеет ограничение меньше, чем теоретический максимум 4 ГБ для любого 32-битного процесса.

ОБНОВЛЕНО

Я прочитал пост в блоге, связанный через TalkingTree, и другой пост, связанный с этим постом. Я не сталкивался с этим конкретным случаем, но у меня было следующее наблюдение: регистрация метрик JRUN может не записывать "максимальные значения", которые вы указали в период пикового использования потока. Я думаю, что это регистрирует метрики с фиксированным, повторяющимся интервалом. Это хорошо для того, чтобы показать вам плавные средние характеристики производительности вашего приложения, но оно может не отражать состояние JRUN непосредственно перед началом возникновения ошибки.

Не зная о внутренней работе управления потоками JRUN, я все еще говорю, что на самом деле не хватает памяти. Возможно, это не из-за нехватки памяти, потому что вашему приложению нужно было выделить память в куче JVM, и ни одна из них не была доступна, но в ней недостаточно памяти, потому что JRUN попытался создать другой поток для обработки входящего запроса, а память кучи, необходимая для поддержки другого потока, не была ' t доступны - другими словами, потоки не являются свободными - им также требуется куча памяти.

Ваши варианты выглядят следующим образом:

  1. Уменьшите объем памяти, используемый вашим приложением в каждом запросе, или
  2. Экспериментально уменьшите значение параметров настройки потока в конфигурации JRUN, чтобы большее количество потоков было поставлено в очередь на обработку вместо того, чтобы становиться работоспособным одновременно, или
  3. Уменьшите количество одновременных запросов в администраторе ColdFusion (страница "Настройка запросов", поле "Максимальное количество одновременных запросов шаблона")

Независимо от того, какой вариант вы используете, я думаю, что правильное решение будет экспериментальным. Вам нужно будет внести изменения и посмотреть, как это повлияет на приложение. У вас есть среда нагрузочного тестирования, верно?

Попробуйте уменьшить максимальный размер кучи. Каждый поток требует собственных ресурсов (наряду с собственным материалом Java). Используемая виртуальная AS - 2 ГБ; 1,2 Гб зарезервировано для кучи. Часть оставшихся 800 МБ используется для кода (текстовые сегменты java и все необходимые библиотеки DLL), затем для JRE и его зависимостей требуются собственные выделения... и потоки: для каждого потока по умолчанию зарезервировано 1 МБ AS (хотя на самом деле фиксируется только страница), 100 потоков = 100 МБ (только для стеков). Теперь добавьте немного дополнительного пространства между различными частями, немного фрагментации... OOM;-)

Другие вопросы по тегам