AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: База знаний и проекты
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 10.01.2023, 14:41   #1  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Lightbulb Распараллеливание пакетной обработки с ограничением количества используемых потоков
На многих проектах мне лично встречался такой типовой сценарий:
  • Есть десятки-сотни-тысячи объектов, которые надо обработать/обсчитать в пакетном режиме. Это могут быть накладные для разноски, импортируемые из очереди сообщения, сеть розничных магазинов для обсчета каких-нибудь скидок/ассортиментов, etc.
  • Реализуется "двухуровневая" логика:
    1. задача-планировщик разбирает очередь сообщений/документов, перебирает магазины и т.п.;
    2. задача-исполнитель обрабатывает один переданный ей объект.
    Пакетная инфраструктура позволяет удобно насоздавать из задачи-планировщика отдельную runtime-задачу на каждый обрабатываемый объект и распараллелить, таким образом, обработку, в том числе задействовав несколько пакетных серверов. Задача-планировщик может настраивать зависимости одних runtime-задач от других, скажем, финальная задача формирования и рассылки отчета может зависеть от завершения всех вычислительных runtime-задач.
  • Есть при этом необходимость ограничить нагрузку такой распараллеливаемой обработки некоторым количеством потоков, чтобы умерить нагрузку на СУБД, и чтоб для других периодических операций остались свободные потоки пакетной обработки.
  • Также может быть желание снизить накладные расходы пакетной инфраструктуры, связанные с планированием и выполнением большого количества пакетных задач.
В стандартном приложении, начиная с AX2009, есть пример пакетирования отдельных задач для уменьшения накладных расходов пакетной инфраструктуры - см. обсуждение классов BatchTaskBundle и BatchTaskBundleAssmebler. Там реализована попытка "взвешивания" отдельных пакетных задач с тем, чтобы пакеты получались примерно одинакового "веса" - в общем случае, чтобы каждый пакет обрабатывал примерно одинаковое количество строк документов. Правда, количество самих пакетов (и, таким образом, потоков пакетной обработки) при этом никак не ограничивается.
Во вложении представлена реализация классов BatchTaskBundleSimple и BatchTaskBundleMaxThreadsAssembler, позволяющих пакетировать отдельные runtime-задачи так, чтобы в итоге ограничить сверху используемое количество потоков пакетной обработки.
X++:
BatchTaskBundleMaxThreadsAssembler  bundleAssembler;
BatchHeader                         batchHeader;
List                                listOfBundles;
SysRunable                          myTask;
RetailStoreTable                    rtlStoreTable;
;
// предположительно мы - задача-планировщик, запущенная в пакетной обработке
batchHeader = BatchHeader::getCurrentBatchHeader();
bundleAssembler = BatchTaskBundleMaxThreadsAssembler::construct(
    BatchHeader::getCurrentBatchTask(),
    RetailParameters::find().MaxBatchThreads); // некое ограничение числа потоков
// нарезаем runtime-задачи на определенное число потоков пакетной обработки
while select StoreNumber from rtlStoreTable
{
    myTask = MyBatchTask::construct();
    myTask.parmStoreNumber(rtlStoreTable.StoreNumber);
    bundleAssembler.addTask(myTask, rtlStoreTable.StoreNumber);
}
// получаем список сформированных пакетов задач - экземпляров BatchTaskBundleSimple
listOfBundles = bundleAssembler.scheduleBundledTasks(batchHeader);
// добавляем еще runtime-задачи, настраиваем зависимости от задач в listOfBundles
// ...
// сохраняем все созданные runtime-задачи и зависимости в текущем пакетном задании
batchHeader.save();
Отличия от стандартных классов следующие:
  • Можно "пакетировать" любые задачи (экземпляры классов) вперемешку, потому что не нужно уметь их взвешивать - учитывается только количество добавляемых задач, равномерно распределяемых по пакетам. В стандартной реализации класс-bundle должен заранее "знать", экземпляры каких классов будут в него добавляться.
  • Можно добавлять экземпляры классов, не являющиеся наследниками RunBaseBatch, достаточно, чтобы они реализовывали SysRunable и SysPackable (да, наследники RunBase тоже можно будет поставить в пакетную обработку ). В стандартной реализации поддерживаются только наследники RunBaseBatch (SysOperationServiceController? неа, не слышали).
  • Можно использовать классы, которые не реализуют статический ::create(container _packedClass), необходимый для распаковки коллекций классов. Все добавляемые runtime-задачи помещаются в List, который затем запаковывается. В стандарте при запуске в пакетной обработке List распаковывается штатными средствами - через List::create(). Если ваш класс не реализует статический ::create(container _packedClass), распаковка List с вашим классом внутри вызовет ошибку времени выполнения. В предложенной реализации List распаковывается "вручную", поэтому добавленным runtime-задачам достаточно реализовывать SysPackable.
  • Можно передать свой BatchHeader для добавления runtime-задач на основе сформированных пакетов и получить на выходе список экземпляров классов этих пакетов без сохранения изменений BatchHeader в пакетном задании. Это позволит, к примеру, добавить другие runtime-задачи в пакетное задание и настроить зависимости их запуска от сформированных задач пакетов (условно, та самая финальная рассылка отчета). Стандартный BatchTaskBundleAssembler предполагает, что кроме формирования пакетов задач в пакетном задании больше ничего делать не нужно, и никакие зависимости других задач от формируемых им пакетов вы уже не настроите.
  • Можно при добавлении runtime-задачи в пакет указать её короткий идентификатор (код заказа/сообщения/магазина/склада/еще что) - потом из таких идентификаторов будут автоматически сформированы заголовки пакетов. Правда, нужно помнить, что BatchCaption штатно имеет длину всего 100 символов.
  • По мере выполнения задач пакета обновляется штатный "градусник", т.е. при выполнении пакетного задания на форме "Просмотр задач" для каждого пакета будет виден прогресс выполнения, пропорциональный количеству завершившихся внутри него задач. Это может быть особенно полезно для службы поддержки - понимать, а не зависло ли пакетное задание.
Нажмите на изображение для увеличения
Название: BatchTaskBundleProgress.png
Просмотров: 45
Размер:	44.4 Кб
ID:	13533
Вложения
Тип файла: zip BatchTaskBundleMaxThreads.zip (5.7 Кб, 110 просмотров)
За это сообщение автора поблагодарили: Stitch_MS (3), axm2017 (5), AvrDen (1), raz (20), Capodastr (1), Ace of Database (10), trud (5), Pandasama (5), Logger (15), LETTO (1), sukhanchik (20), DarkSpirit22 (2), -DocSerzh- (1).
Теги
пакетная обработка, пакетное задание, полезное

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Сервер пакетной обработки IKA DAX: Администрирование 4 02.08.2013 13:14
Запуск пакетной обработки (batch) в последний день месяца petr DAX: Функционал 10 03.12.2010 00:11
Ошибка при выполнении пакетной обработки Dolores DAX: Администрирование 3 05.08.2010 16:11
Снять задание сервера пакетной обработки fomenka DAX: Программирование 9 24.04.2007 14:33
Распараллеливание процесса пакетной обработки 6apcyk DAX: Программирование 7 04.04.2006 10:05

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 08:34.