При работе с крупными информационными системами, особенно в распределенных информационных базах (РИБ) с большим количеством узлов, администраторы и разработчики часто сталкиваются с проблемой «шторма» фоновых заданий. Суть проблемы заключается в том, что при перезагрузке службы агента сервера 1С или временной недоступности базы данных, все регламентные задания, чье время запуска подошло или было пропущено, пытаются стартовать одновременно. В результате сервер испытывает колоссальную нагрузку на CPU и дисковую подсистему, что может привести к полной неработоспособности системы.
В этой статье мы подробно разберем, как эффективно управлять очередностью выполнения задач, проанализируем архитектурные и программные методы ограничения нагрузки и посмотрим на конкретные примеры реализации контроля запуска.
Одним из самых простых и надежных способов избежать одновременного запуска является объединение нескольких задач обмена в один сценарий. Вместо того чтобы создавать 30 отдельных регламентных заданий для каждого узла РИБ, мы можем создать одно задание, которое будет обходить все узлы последовательно.
Рассмотрим подробнее этот подход. Когда мы используем один сценарий для нескольких планов обмена, платформа выполняет их по очереди: сначала завершается обмен с узлом А, затем начинается обмен с узлом Б и так далее. Это гарантирует, что в любой момент времени активен только один поток обмена, что существенно снижает нагрузку на базу данных.
Некоторые разработчики опасаются, что последовательный обмен будет длиться слишком долго. Однако, как показывает практика, это зачастую эффективнее, чем «положить» сервер массовым запуском. К тому же, если один сеанс обмена блокирует базу слишком сильно, причину стоит искать в оптимизации самих запросов обмена или настройках блокировок, а не в самом факте последовательного запуска.
Если нам все же необходимо иметь независимые регламентные задания, мы можем добавить в код самого задания проверку на количество уже запущенных процессов. Для этого воспользуемся методом ФоновыеЗадания.ПолучитьФоновыеЗадания().
Разберем по шагам, как реализовать такую проверку в начале процедуры регламентного задания:
Посмотрим на пример реализации такого контроля:
Процедура ВыполнитьОбменДанными() Экспорт
// Параметры фильтрации: ищем активные задания с этим же именем метода
СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("Состояние", СостояниеФоновогоЗадания.Активно);
СтруктураОтбора.Вставить("ИмяМетода", "ОбменыДанными.ВыполнитьОбменДанными");
АктивныеЗадания = ФоновыеЗадания.ПолучитьФоновыеЗадания(СтруктураОтбора);
// Если запущено более 3-х экземпляров, выходим
Если АктивныеЗадания.Количество() > 3 Тогда
ЗаписьЖурналаРегистрации("Обмен данными", УровеньЖурналаРегистрации.Предупреждение, , ,
"Превышен лимит одновременно работающих обменов. Задание пропущено.");
Возврат;
КонецЕсли;
// Основная логика обмена...
КонецПроцедуры
Этот метод позволяет динамически регулировать нагрузку, даже если платформа инициировала старт всех тридцати заданий после перезагрузки. Реально работать останутся только первые несколько, а остальные «отвалятся» и подождут следующего цикла по расписанию.
Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), крайне рекомендуется использовать подсистему «Очередь заданий». Вместо жесткой привязки к расписанию платформы, задачи помещаются в специальную очередь (регистр сведений), а их выполнение контролирует специальный обработчик.
Проанализируем ситуацию: в БСП механизм очереди позволяет задавать количество одновременно выполняющихся потоков. Это более гибкий инструмент, так как он позволяет централизованно управлять приоритетами. Если сервер перегружен, очередь просто замедлит обработку новых задач, не создавая новых фоновых процессов до освобождения ресурсов.
В высоконагруженных системах часто применяется стратегия выноса функционала обменов в отдельный контур. Выясним причину, почему это эффективно: при интенсивных обменах основные таблицы базы данных могут блокироваться, мешая оперативной работе пользователей в главном офисе.
Существует два варианта реализации:
Это простой «хак», который помогает разнести моменты фактического начала активной работы заданий. Даже если задания стартовали одновременно, мы можем заставить их подождать случайное количество времени перед началом транзакций.
Рассмотрим пример использования генератора случайных чисел для создания паузы:
Процедура ВыполнитьОбменСПаузой() Экспорт
Генератор = Новый ГенераторСлучайныхЧисел();
// Пауза от 1 до 120 секунд
СекундОжидания = Генератор.СлучайноеЧисло(1, 120);
// Приостанавливаем выполнение потока
Приостановить(СекундОжидания * 1000);
// Приступаем к обмену
ПродолжитьОбмен();
КонецПроцедуры
Важный момент: использование функции Приостановить() (или аналогичных методов ожидания) позволяет эффективно распределить пиковую нагрузку на диск и процессор, которая обычно возникает в самом начале выполнения обмена при чтении данных.
Не забывайте о возможностях самой платформы 1С:Предприятие 8.3 по управлению ресурсами. В настройках кластера можно задать следующие параметры, которые помогут локализовать проблему «шторма» заданий:
Таким образом, комбинируя программные методы контроля (проверка активных фоновых заданий) и архитектурные решения (последовательные сценарии или выделенные серверы), можно добиться стабильной работы системы даже при наличии десятков регулярных обменов.