Служба часов и пакетная обработка Java EE

1

контекст

Я собираюсь разработать решение для переноса огромной PL/SQL-системы на Java. Первым шагом является миграция некоторых заданий ETL, которые:

  1. Читает CSV, XML, (XLS, что является новым требованием) и позиционные файлы из нескольких источников ftp/sftp
  2. Обработайте файлы в соответствии с правилами, хранящимися в базе данных, и напишите результаты в таблицу базы данных.

В настоящее время это делается несколькими процедурами магазина и рабочими местами.

Моя компания открыта для предложений (если она может работать в GlassFish 4 и делиться своими механизмами пула регистрации и подключения, а также с консолью администратора, это плюс).

Я провел немного исследований, и на мой взгляд оказались следующие варианты:

  1. Java EE 7 Batch Processing, звучит просто и особенно хорошо подходит для GlassFish 4.
  2. Spring Batch несколько более зрелый и очень похож на стандарт Java EE 7 (который, вероятно, был основан на нем).
  3. Apache Camel, звучит мощно и избавит нас от многократной игры с такими библиотеками, как Apache POI, но также выглядит несколько сложным. Также я не уверен, что это лучше всего подходит для работы (ETL над огромными файлами).
  4. Кука все одна. Я мог бы создать Application Client для запуска Quartz/Spring Scheduler или даже EJB Timers

Хотя я по-прежнему открыт для предложений (рекомендации были бы хорошими), наилучшим образом подходит, по-видимому, Java EE 7 Batch Processing.

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

проблема

Я прочитал несколько руководств по пакетной обработке Java EE и, во всех них, какой-то Servlet или EJB Timer отвечает за запуск Jobs:

JobOperator jobOperator = BatchRuntime.getJobOperator(); 
jobOperator.start("job", properties);

Я мог бы легко загрузить проект web/ejb и сохранить пул для изменений. Но я думал о модели push:

  1. Приложение для клиентской консоли приложения
  2. Главные часы для каталогов для новых файлов
  3. Когда появится новый файл, он запустит новое задание.

Мои сомнения:

  1. Является ли эта стратегия возможной/целесообразной?
  2. Нужна ли мне очередь JMS или какая-то стратегия производителя/потребителя в середине или мне нужно просто вызвать jobOperator.start для каждого файла и доверять слою пакетной обработки для управления ресурсами приложения? Другими словами, если тысяча файлов отправляется в мою папку одновременно, и я вызываю jobOperator.start тысячу раз, GlassFish 4 сделает какой-то умный enqueuing или мне нужно создать какой-то Gate, чтобы выполнялось не более n заданий одновременно?
  • 0
    Spring Batch настоятельно рекомендуется. Я бы также посмотрел на Spring Integration .
Теги:
batch-processing
java-ee
glassfish

2 ответа

1
Лучший ответ

Я уже реализовал проект с пакетной обработкой в Wildfly (Jboss AS). Я не знаком с деталями конфигурации Glassfish (не использую его больше, потому что "потерял поддержку предприятия"), однако я могу дать вам некоторые идеи и рекомендации в соответствии с моим опытом. Кроме того, обратите внимание, что Spring и пакетная спецификация. на EE 7 очень похожи, и ваше решение использовать любую технологию должно зависеть от того, "что еще" вы хотите достичь с помощью своего приложения, помимо пакетной обработки. Вы хотите легко поддерживаемый веб-интерфейс? Вы хотите депонировать REST api?, и т.д.

Задачи ETL, которые вы описываете, подходят для моделей с шагами и кусками в спецификации EE 7, поэтому, если вы уже пытались разработать некоторые тесты, вы, возможно, заметили, что вам по-прежнему необходимо кодировать считыватели и картотеки для каждого спецификация файла. Ваши источники чтения довольно стандартизированы, и вы легко найдете библиотеку для чтения/потока и обработки своих данных.

Проект, который я реализовал, довольно прост. Клиенты uplodad файлы, которые необходимо обработать, чтобы прокормить хранилище данных. Эта услуга находится в "облаке". Файлы имеют определенную спецификацию и должны быть в формате CSV. Большинство результатов обработки - это "Упрощение" и "удаление предыдущей вставки". У пользователя есть веб-интерфейс, на котором должны отображаться файлы и метаданные пакетной обработки (состояние обработки, даты, отклоненные элементы и т.д.). Поскольку это облачная служба, файлы не должны размещаться локально на каждом сервере (используя S3).

Итак, первое, что нужно спроектировать, - это шаги куска. Я не хотел иметь реализацию для каждой спецификации файла. Так что я сделал, чтобы создать "подходящую для всех случаев" реализацию файлов процессов в соответствии с содержащимися в них метаданными, а также самой конфигурацией заданий. Это легкая часть. Второе, о чем нужно подумать, это администрирование обработки и метаданных. Здесь я разработал REST api и веб-интерфейс, который его использует. После всего этого, будет ли он масштабироваться? У Wilfly есть параметры конфигурации резьбы для пакетной обработки, и вы можете увеличить или уменьшить доступность потоков для JobOperator. Рабочие места не отправляются, если доступных потоков недостаточно. Так что происходит с этими просьбами? Ну, они могут находиться в памяти, можно создать резервную сессию с поддержкой состояния, вы можете определенно реализовать MQ-прослушиватель запросов обработки в очереди. То, что я сделал, было намного проще. У компании нет ресурсов для поддержки кластера, поэтому была эластичная конфигурация, которая будет расширяться в зависимости от потребления процессора и объема запросов. До сих пор приложение обработало 10 ТБ данных, от 15 клиентов, и при максимальном запросе/обработке пик, 3 экстренных экстента загорелись.

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

Не стесняйтесь спрашивать меня.

С уважением.

EDIT: забыл упомянуть. Я действительно не рекомендую использовать клиент приложения, если вы уже не нашли что-то в своей организации. Недавние ограничения безопасности и механизм обновления java SE сделали реальную проблему для поддержки такого рода развертываний. Подумайте в Интернете.

  • 0
    Ра, спасибо за всю информацию и очки о масштабируемости. У меня есть два последующих вопроса: Jobs are not submitted if there are not enough threads available , под «не отправлено» вы подразумеваете, что jobOperator.start завершается с ошибкой или что он каким-то образом ставится в очередь, пока не станет доступным поток? И второй вопрос касается Application Client (и под этим я не подразумеваю Applet, я имею в виду просто клиент приложения с основным методом для прослушивания событий файла и запуска пакета процесса каким-либо образом - либо напрямую, либо с JMS-очередью, как было предложено. по воле).
  • 0
    Будет ли больно поддерживать такого тонкого клиента? Я думал, что большинство болезненных ограничений безопасности были нацелены на Applets, Web Start и т. Д. (Это был бы Тонкий клиент, развернутый через as-admin).
Показать ещё 7 комментариев
1

Я бы подошел к этому так.

Мое молот для этого варианта использования будет Java Watch Service, Servlet, JMS-очередь и пакетная служба.

Во-первых, Watch Service - это Java 7, чтобы обрабатывать мониторинг файловой системы.

Я бы написал реализацию Watch Service, и я бы запускал ее в потоке.

Куда запускается нить?

Официально вы, вероятно, должны использовать JCA для этого. Но, JCA имеет плохую боль, чтобы работать с, недоиспользованным, таким образом, документированным. Имеются убедительные примеры, но это просто не общая технология в стеке Java EE.

Другим местом является асинхронный вызов Session Bean. Там ничего, что предлагает, не может быть долгоживущими призывами. Вы можете встать с @Singleton Session Bean, с @Startup, вызвать метод async из метода @PostConstruct и отпустить его. Затем, в @PreDestroy сигнализирует о длительном запуске метода, чтобы он мог полностью отключиться. Все это должно быть спецификацией, переносимой и, согласно Хойлу.

Третье место - вам ServletContextListener, который является до-Java EE 6, чтобы разместить привязку кода к жизненному циклу приложения. Здесь вы должны создать поток самостоятельно в контекстеInitialized метод, а затем оторвать его в методе contextDestroyed.

Создание потоков здесь "менее определено", но я делал это в течение многих лет и никогда не испытывал проблем.

Теперь, когда у вас есть ваш сервис, служба (IMHO) будет делать две вещи.

1) Будет понятно, когда в каталог поступит новый файл, и когда он это сделает, он будет MOVE (mv, переименовать) файл в параллельный "обрабатывающий" каталог. Причина в том, что это говорит о том, что файл переместился с входящего на обработку, что файл находится в процессе. Это очевидно из списка каталогов, независимо от того, что он делает. Помните, что система может идти по середине через файл.

2) После перемещения разместите имя файла и любые другие метаданные в очереди JMS и добавьте инструмент MDB в пакетное задание.

Зачем добавлять очередь JMS? Это приносит пару функций партии. Во-первых, это отличный способ получить материал "извне" в счастливый трансакционный контекст, который нравится EJB, внутри него. Во-вторых, он транзакционный. Вы можете, в зависимости от вашего случая использования ETL, иметь MDB непосредственно обрабатывать задание. И при этом вы просто не подтверждаете сообщение из очереди до завершения обработки (и файл удаляется или перемещается из каталога "обработка"). В идеальном мире очередь сообщений содержит сообщения, соответствующие файлам в каталоге обработки. Когда обработка завершена, метод возвращается, сообщение получает "commit", и все готово. Если система выйдет из строя, это автоматически перезапустится с самого начала (поскольку сообщение все еще находится в очереди и никогда не удалялось).

MDB, настраивая его экземпляры, также может задерживать число одновременных заданий. Настройте 10 экземпляров, одновременно обрабатывайте только 10 файлов. Но это может быть слишком просто, слишком грубо. Например, нет приоритета (сначала нужно сначала подать заявку). Но это может сработать для вас.

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

Но мне нравится демаркация MDB. Даже если все это задача состоит в создании записи Batch для имени файла, MDB является хорошим привратником.

И это в значительной степени.

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

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

Получайте удовольствие, делитесь и наслаждайтесь.

Добавления к вопросу:

Фактически нет никакой ценности, чтобы внешний процесс управлял службой часов. Один связанный с жизненным циклом сервера легче поддерживать. Приходят на ум две вещи. Если сервер не работает, файл будет просто складываться в файловой системе до тех пор, пока сервер не будет запущен заново, поэтому вы не потеряете данные. Если у вас есть внешняя услуга, вы либо отправляете сообщения на мертвый сервер, либо вам необходимо организовать и управлять сервером JMS отдельно от сервера приложений. В этом случае у вас теперь есть 3 процесса управления: Watch service, JMS Server и сервер приложений, а не только сервер приложений.

Я согласен с другим плакатом, который, если вы решите пойти с внешней службой, в любом случае, простое приложение Java SE публикует простые сообщения в службе REST JAX-RS на сервере или даже тривиальный сервлет очень много, МНОГО более просто поддерживать, этап и развертывание, чем клиент приложения. Если вы сделаете так, вы можете написать службу часов в чем-то совершенно другом.

Но поскольку сервер (якобы) имеет прямой доступ к файловой системе с файлом, на самом деле нет никакой мотивации, чтобы разорвать эту службу за пределами контейнера. Поместите весь комплект в EAR и получите его. Просто простое управление.

  • 0
    Привет Уилл, спасибо за отличный ответ, основанный на личном опыте. Ваша стратегия звучит очень хорошо. С архитектурной точки зрения было бы неправильно использовать консольный клиент приложений для сервера наблюдения? Я думал о чем-то вроде: App Client -> Watch Service -> Move and Enqueue для процессов (помещая сообщение в очередь). MDB будет обрабатывать запросы (или, может быть, я смогу заменить MDB временным @Schedule который будет обрабатывать каждый файл в очереди сразу). Теоретически мне не понадобится долго работающий синглтон / сервлет. Как это звучит для вас?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню