Рубрики
Без рубрики

Рекомендации по пакетной обработке

Автор оригинала: Vlad Mihalcea.

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

С точки зрения типа ввода элементы обработки могут поступать путем опроса хранилища элементов обработки или путем их отправки в систему через очередь. На следующей диаграмме показаны три основных компонента типичной системы пакетной обработки:

  • компонент ввода (загрузка элементов путем опроса или из входной очереди)
  • процессор: основной компонент логики обработки
  • компонент вывода: выходной канал или хранилище, куда будут отправлены результаты

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

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

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

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

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

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

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

Хранение результатов работы в памяти не очень продумано. Выбор хранилища с сохраняемостью (коллекция с ограничением MongoDB) – лучший вариант.

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

for(GeocodeRequest geocodeRequest : batchRequests) {
   mapsService.resolveLocation(geocodeRequest);
}

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

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

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

  • очереди сообщений
  • каналы опроса
  • трансформаторы
  • разделители/агрегаторы
  • задерживающие

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

Для получения дополнительной информации об EIP вы можете проверить отличную Весеннюю интеграцию фреймворк. Я использую его уже три года, и после того, как вы сделаете прививку, вы предпочтете его процедурному программированию.