среда, 24 апреля 2013 г.

Соображения по использованию WorkManager'ов на сервере приложений Oracle WebLogic

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

Показания для вмешательства в работу пула потоков


Прежде всего следует помнить, что использование стандартного WorkManager'а (default) как правило является вполне допустимым решением: на каждое развернутое на сервере приложение будет создан свой WorkManager, имеющий настройки по-умолчанию. Дополнительные менеджеры потоков нужно определять лишь в следующих случаях:

  • Приоритеты потоков по-умолчанию - все потоки имеют равный приоритет - нас не устраивают (Fair Share).

  • Необходимо задать время ответа, к которому сервер приложений должен стремиться (Response Time).

  • Возможны взаимоблокировки при взаимодействии сервер-сервер, в данном случае необходимо настроить WorkManager с явно заданным ограничением числа потоков снизу (Minimum Threads Constraint).

  • При работе приложения используется общий для нескольких потоков пул соединений JDBC, тогда необходимо ограничить число этих потоков сверху (Maximum Threads Constraint).

Отдельно стоит заметить, что если на сервере приложений Oracle WebLogic развернута Oracle Service Bus, то для избежания взаимоблокировок при использовании Service Callout'ов необходимо, чтобы вызываемые таким образом сервисы имели отдельные WorkManager'ы. Подробнее про модель потоков OSB можно прочитать в одноименной статье.


Правила настройки WorkManager'ов


При настройке WorkManager'ов следует придерживаться следующих правил:

  • WorkManager'ы могут быть настроены на уровне приложения путем определения их в файле weblogic-application.xml. Такой способ настройки облегчает переносимость приложения между различными средами: разработки, тестирования, промышленной эксплуатации.

  • Необходимо определиться будут ли настройки, такие как Request Class или Threads Constraint, разделяемыми между различными WorkManager'ами. Если будут, то их необходимо описать вне определения WorkManager'а. Однако, следует помнить, что если один такой компонент, например Maximum Thread Constraint, используется несколькими WorkManager'ами, то соответствующее число потоков распределяется между этими менеджерами. Например, если WorkManager'ы A, B и C используют Maximum Thread Constraint D, равный четырем потокам, и для WorkManager'а A выделено из пула три потока, а для WorkManager'а B - один, то WorkManager'у C потоков не достанется.

  • Для некоторых приложений, например для Oracle Service Bus, нельзя определить WorkManager'ы с помощью дескрипторов развертывания. В таком случае их необходимо определить глобально с помощью консоли администрирования сервера приложений Oracle WebLogic. Определенные глобально WorkManager'ы могут использоваться всеми приложениями, развернутыми на том же сервере.

Правила поиска WorkManager'а приложением


При настройке дополнительных WorkManager'ов возможна ситуация, когда не понятно почему приложение ведет себя не так, как от него ожидает администратор. Для решения подобных проблем необходимо понимать правила, по которым приложение ищет WorkManager, и что оно делает, если не может его найти. Данные правила довольно просты:

  • Прежде всего приложение ищет локальный WorkManager, определенный в его дескрипторе развертывания.

  • Если локальный WorkManager с заданным именем не найден, то ищется WorkManager, определенный на уровне сервера.

  • Если не найден WorkManager, определенный на уровне сервера, то применяются следующие правила: настройки Fair Share устанавливаются в значение по-умолчанию, для constraints и capacity устанавливается значение null - данные ограничения не будут применяться.

Заключение


В качестве заключения стоит отметить, что управление потоками в среде сервера приложений осуществляется довольно просто и в большинстве случаев декларативно. В принципе, самонастраиваемый пул потоков сервера приложений Oracle WebLogic является довольно интеллектуальным компонентом, который может самостоятельно устанавливать оптимальное для конкретной конфигурации число потоков. Однако, если поведение пула по-умолчанию вас не устраивает, то его всегда можно настроить под свои нужды согласно описанным в данной заметке соображениям.

Хочу напомнить, что очень грубая ошибка - пытаться создавать потоки в управляемой среде с помощью явного обращения к классу Thread. Такие потоки не будут управляться сервером приложений и могут привести к значительному снижению производительности. Если в приложении нужно создать отдельный поток, то необходимо использовать CommonJ API.

Понравилось сообщение - подпишитесь на блог и Twitter

7 комментариев:

Васильев Валерий (oldvasya) комментирует...

Павел, помогите разобраться с некоторыми моментами:
Для одного приложения заведены 10 Work Manager - для обращения к 10 различным ресурсам. Ресурсы нестабильны, и из-за этого частенько возникают STUCK-треды, поэтому хочется ограничить запросы к тем ресурсам, которые вдруг стали "тормозить".
Ограничивать пытаемся с помощью Constraints которые "привязаны" к каждому Work Manager.
Допустим нужно, чтоб каждый Work Manager мог распоряжаться только 10 потоками - не больше. Тогда, если все его потоки уйдут в STUCK, будет не очень критично для системы, т.к. все остальные будут работать.
Выставление Maximum Threads Constraint = 10 и привязка его ко всем WorkManager, не приводит к нужному эффекту. Смоделировав "падение" одного ресурса на тестовом стенде, мы наблюдаем что НА КАЖДОМ из WorkManager присутствуют STUCK треды, причем их количество больше 30 !!! Хотя судя по вашему описанию, это значение распределяется среди всех WorkManager и по идее должно быть = 1 для каждого.
Выставление Capacity Constraint = 10 и привязка его ко всем WorkManager также ни на что не влияют.
Вопросы в следующем:
1. Как все-таки правильно ограничить количество потоков доступных каждому WorkManager и можно ли это сделать?
2. Почему на WorkManager, которые "завязаны" на работающий ресурс, также видны STUCK-треды?
3. Есть ли необходимость определять WorkManager в дескрипторах (web.xml, weblogic-application.xml) если в приложении можно просто достучаться до них по JNDI (new InitialContext().lookup(...))

Pavel Samolisov комментирует...

Если я правильно вас понял, то вы создали один MaxThreadConstraint и связали его со всеми WM'ами. Я писал в заметке: "Однако, следует помнить, что если один такой компонент, например Maximum Thread Constraint, используется несколькими WorkManager'ами, то соответствующее число потоков распределяется между этими менеджерами.", возможно это звучит путано, но суть в том, что для каждого WM'а нужно создавать свою MaxThreadContraint.

Никто не гарантирует, что если назначить один MaxThreadConstraint на несколько WM'ов, то ограничения распределятся равномерно, а судя по тому что вы пишите (ограничили 10-ю, но в реальности имеем 30 потоков), то такое поведение вообще слабо определено. На всякий случай, после увеличения MaxThreadConstraint или его назначения нужно перезапустить сервер даже если он этого явно не просит. Не всегда данные изменения применяются сразу.

Для критичных операций я бы посоветовал настроить WM'ы с указанием MinThreadConstraint, опять же по одному constraint на WM.

Понятие STUCK-thread не обозначает, что тред непременно завис и никогда не проснется, это лишь значит, что операция выполняется слишком долго - больше, чем указано в Stuck Thread Max Time на вкладке Tuning настроек сервера (по-умолчанию - 10 минут). Если операция выполняется, например, 11 минут, то поток будет отмечен как STUCK, но затем, по завершении операции, выйдет из этого состояния.

По поводу дескрипторов. Вообще по спецификациям Java EE определять нужно. К DataSource тоже можно достучаться через JNDI, но никто не гарантирует, что это будет работать на всех серверах приложений без определения ссылки на ресурс в дескрипторе развертывания. К тому же указание ссылки на ресурс в web.xml позволяет в дальнейшем подменить JNDI-имя в weblogic.xml, а значит и использовать это имя в плане развертывания (plan.xml).

Васильев Валерий (oldvasya) комментирует...

Павел, спасибо за столь развернутый ответ.
Действительно, мы создали один MaxThreadConstraints и ситуация вышла из рамок нашего понимания ))
Сделали, как описано в статье и все стало на свои места. Даже в самых "сложных" условиях более 10 потоков на WorkManager не наблюдается.

Остался только непонятный момент. Мы "забиваем" стаками один WorkManager, а на вкладке Health приложения видим, что на всех WorkManager, которые относятся к приложению обнаружены STUCK-треды. Причем на всех одинаковое количество.
Мы предполагаем, что Weblogic просто знает число потоков, которые у него в STUCK находятся, но не знает на каком конкретно WorkManager. Вот и пишет, что на всех сразу по 10 STUCK. Или причина в чем-то другом?

Pavel Samolisov комментирует...

Возможно, что и так, хотя это странно.

Попробуйте еще снять дамп потоков с помощью jstack или с помощью кнопки Dump Thread Stack на странице Monitoring -> Threads.

Pavel Samolisov комментирует...

Еще вопрос. У вас WebLogic какой версии?

Васильев Валерий (oldvasya) комментирует...

Наверняка, так. В мониторинге сервера мы видели что конкретный WM были со стаками, а в health писал, что на каждом WM стаки.

Weblogic 10.3.0.0

Pavel Samolisov комментирует...

Довольно старый, может быть в нем были проблемы с привязкой Stack Thread'ов к WM'ам в мониторинге. Можно попробовать поискать что-то по этому поводу на Металинке.

Отправить комментарий

Любой Ваш комментарий важен для меня, однако, помните, что действует предмодерация. Давайте уважать друг друга!