Как EJB может параллелизировать длинное, ЦП интенсивный процесс?

Приложение имеет ЦП интенсивный долгий процесс, который в настоящее время работает на одном сервере (метод EJB) последовательно, когда клиент запрашивает это.

Теоретически возможно (с концептуальной точки зрения) разделить тот процесс в блоках N и выполнить их параллельно, пока вывод всех параллельных заданий может быть собран и объединился прежде, чем передать его обратно клиенту, который инициировал процесс. Я хотел бы использовать это распараллеливание для оптимизации производительности.

Как я могу реализовать это распараллеливание с EJBs? Я знаю, что мы не должны создавать потоки в методе EJB. Вместо этого мы должны опубликовать сообщения (один на задание), чтобы быть использованными управляемыми сообщениями компонентами (MDBs). Но тогда это больше не был бы синхронный вызов. И быть синхронным, кажется, требование в этом случае, так как я должен собрать вывод всех заданий прежде, чем передать его обратно клиенту.

Существует ли решение для этого?

13
задан b.roth 5 January 2010 в 12:25
поделиться

5 ответов

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

Используйте WorkManager из commonj API. Он позволяет управлять потоками в контейнере Java EE и специально разработан в соответствии с вашим случаем использования. Если вы используете WebSphere или WebLogic, то эти API уже доступны на вашем сервере. Для других, вам придется поместить в себя решение сторонних разработчиков.

WorkManager info

Связанные с этим вопросы Почему не рекомендуется использовать нерестовые нити

6
ответ дан 1 December 2019 в 21:52
поделиться

Есть множество способов сделать это.

Во-первых, вы можете использовать EJB таймер для создания процесса выполнения, который запустится немедленно. Это хорошая техника для порождения процессов в фоновом режиме. Таймер EJB ассоциируется с конкретной реализацией фасоли сеанса. Вы можете либо добавить EJB таймер к каждому Session Bean, который вы хотите иметь возможность сделать это, либо у вас может быть один Session Bean, который затем может вызвать логику вашего приложения через некоторый механизм диспетчеризации.

Для меня, я передаю сериализуемый блок параметров вместе с именем класса, который отвечает специфическому интерфейсу, к общему Session Bean, который затем выполняет этот класс. Таким образом, я могу легко сделать фоновым большую часть всего, что угодно.

Одним из предостережений о таймере EJB является то, что таймеры EJB являются постоянными. После создания таймера EJB остается в контейнере до тех пор, пока его работа не будет завершена или отменена. Суть в том, что если у вас длительный процесс, и сервер выходит из строя, то при перезапуске процесс продолжится, и вы получите обратно резервную копию. Имейте в виду, что это может быть хорошей вещью, но только если ваш процесс готов к перезапуску. Но если у вас есть простой процесс итерации через "10,000 элементов", если сервер падает на пункте 9,999, когда он возвращается назад, вы можете легко увидеть, что он просто начинается заново с пункта 1. Все это работает, просто предостережение, чтобы быть в курсе.

Другой способ сделать что-то фоновым - это использовать очередь JMS. Поставьте сообщение в очередь, и обработчик запустится айснхронно от остальной части вашего приложения.

Умная часть здесь, и кое-что, что я также сделал, используя работу с таймером Bean, это то, что вы можете управлять тем, сколько "рабочих мест" будет запущено в зависимости от того, сколько MDB экземпляров вы настроили в системе.

Итак, для конкретной задачи запуска процесса в нескольких параллельных блоках, я беру задачу, разбиваю ее на "части", а затем посылаю каждый кусочек в очередь сообщений, где MDB исполняют их. Если я разрешаю 10 экземпляров MDB, я могу иметь 10 "частей" любой задачи, выполняемой одновременно.

На самом деле это работает удивительно хорошо. Это немного перегружает процесс, разделяя его на части и маршрутизируя через очередь JMS, но это все, по сути, "время запуска". Как только он запускается, вы получаете реальную выгоду.

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

Я обнаружил, что после того, как вы отодвинули длинно выполняющийся процесс в фоновом режиме, вы можете заплатить за то, чтобы иметь менее постоянный доступ к этому процессу. То есть, нет никаких причин отслеживать непосредственно сами выполняющиеся классы, просто заставьте их опубликовать интересную информацию и статистику в базе данных, или JMX, или что угодно, вместо того, чтобы иметь что-то, что может отслеживать объект напрямую, потому что он занимает одно и то же пространство памяти.

Я легко смог настроить фреймворк, который позволяет запускать задачи либо на EJB таймер, либо на MDB очередь рассеяния, задачи одни и те же, и я могу отслеживать их прогресс, останавливать их и т.д.

Вы можете объединить технику рассеяния, чтобы создать несколько заданий EJB таймера. Одним из бесплатных преимуществ MDB является то, что он действует как пул потоков, который может дросселировать ваши задания (так что вы не будете внезапно насыщать вашу систему слишком большим количеством фоновых процессов). Вы получаете это "бесплатно", просто используя функции управления EJB в контейнере.

Наконец, Java EE 6 имеет новый "асинхронный" (или что-то вроде того) классификатор для методов Session Bean. Я не знаю подробностей, как это работает, так как мне еще предстоит поиграть с новым контейнером Java EE 6. Но я полагаю, что вы, вероятно, не захотите менять контейнеры только для этой подсистемы.

.
10
ответ дан 1 December 2019 в 21:52
поделиться

Однажды я участвовал в проекте, в котором транзакции ЕЕБ длились до 5 часов одновременно. Aargh!

В этой же заявке был консультант-специалист БЕА, который утверждал, что они запускают дополнительные нити из транзакций. Несмотря на то, что это не рекомендуется в спецификациях и в других местах, это не приводит к автоматическому провалу. Вы должны знать, что ваши дополнительные потоки находятся вне контроля контейнера и, таким образом, если что-то пойдет не так, это ваша вина. Но если вы можете быть уверены, что количество потоков, запущенных в худшем случае, не превышает разумных пределов, и что все они заканчиваются чисто в разумные сроки, то вполне возможно, что так и будет работать. На самом деле, в вашем случае это звучит как почти единственное решение.

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

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

.
1
ответ дан 1 December 2019 в 21:52
поделиться

Вы достаточно хорошо проанализировали ситуацию, и нет, для этого нет отца, который бы соответствовал модели EJB.

Создание потоков в основном запрещено, так как обходит стратегию управления потоками сервера приложения , а также из-за транзакций .

Я работал над проектом с похожими требованиями и решил породить дополнительные потоки (идя тогда против sepc). Операция по распараллеливанию была только для чтения, поэтому она работала по транзакции (в принципе, нить не имела бы связанных с ними транзакций). Я также знал, что не буду порождать слишком много потоков за один вызов EJB, так что количество потоков не было проблемой. Но если ваши потоки должны изменять данные, то вы нарушаете транзакционную модель EJB серьезно. Но если ваша работа в чистом вычислении, это может быть нормально.

Надеюсь, это поможет...

.
1
ответ дан 1 December 2019 в 21:52
поделиться

EJB - это, в конечном счете, транзакционный компонент для системы клиент-сервер, обеспечивающий семантику запроса / ответа. Если вы оказались в положении, когда вам нужно пометить длительную транзакцию в рамках цикла запроса / ответа, значит, где-то ваш системный архитектор (ure) ошибся.

Ситуация, которую вы описываете, четко и правильно обрабатывается архитектурой, основанной на событиях, с серверной частью обмена сообщениями. Первоначальное событие инициирует процесс (который затем может быть тривиально распараллелен, если рабочие подписываются на тему события), а сам процесс агрегирования вызывает событие по завершении. Вы по-прежнему можете сжать эту последовательность в рамках цикла запроса / ответа, но при необходимости вы нарушите букву и дух спецификаций архитектуры системы Java EE.

4
ответ дан 1 December 2019 в 21:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: