При администрировании крупных и высоконагруженных информационных систем на базе платформы «1С:Предприятие 8.3» часто возникает задача оптимизации производительности кластера серверов. Один из наиболее эффективных инструментов для этого — Требования назначения функциональности (ТНФ). С их помощью мы можем гибко распределять нагрузку, например, переносить выполнение тяжелых фоновых задач (таких как расчет себестоимости, закрытие месяца или формирование сложных аналитических отчетов) на специально выделенные рабочие серверы, освобождая основные рабочие серверы для комфортной и быстрой интерактивной работы пользователей.
Однако на практике администраторы и разработчики часто сталкиваются с ситуацией, когда созданное правило ТНФ для конкретного фонового задания просто игнорируется платформой, и тяжелая задача продолжает выполняться на общем сервере, перегружая систему. В этой статье мы подробно разберем, почему так происходит, проанализируем внутренние механизмы платформы «1С:Предприятие» и Библиотеки стандартных подсистем (БСП), а также подробно рассмотрим три практических способа решения этой проблемы.
Рассмотрим ситуацию, с которой часто начинают настройку ТНФ: администратор пытается указать в требованиях усеченное имя общего модуля без указания конкретного экспортного метода. Например, записывает дополнительный параметр в виде: BackgroundJob.CommonModule.ЗакрытиеМесяцаСервер. Расчет строится на известной цитате из документации ИТС: «Дополнительный параметр проверяется на совпадение с началом соответствующего параметра объекта требования».
Кажется логичным, что если фактический путь фонового задания начинается с этой строки, то платформа должна перенаправить его на выделенный сервер. Но это предположение ошибочно из-за неверной трактовки логики сопоставления. Разберем по шагам, как платформа проверяет это соответствие:
BackgroundJob.CommonModule.ИмяОбщегоМодуля.ИмяМетода.BackgroundJob.CommonModule.ЗакрытиеМесяцаСервер является началом для BackgroundJob.CommonModule.ЗакрытиеМесяцаСервер.ВыполнитьЗакрытие. Однако платформа ожидает от ТНФ строго структурированные параметры. Попытка сократить шаблон до имени модуля без указания метода приводит к тому, что платформа не может корректно распознать и применить это правило для динамических фоновых заданий, так как структура вызова нарушается. Платформа не поддерживает маски и символы подстановки (например, звездочки) для частичного совпадения имен модулей при вызове из кода встроенного языка.Даже если мы исправим первую ошибку и укажем в ТНФ полный путь к методу (например, BackgroundJob.CommonModule.ЗакрытиеМесяцаСервер.ВыполнитьЗакрытие), в большинстве типовых конфигураций 1С (таких как ERP, Комплексная автоматизация, Управление торговлей, Бухгалтерия предприятия) это правило все равно работать не будет. Выясним причину этого поведения.
Дело в том, что в современных конфигурациях длительные операции практически никогда не запускаются напрямую через платформенный метод ФоновыеЗадания.Выполнить(). Вместо этого используется стандартизированный механизм БСП. Посмотрим на упрощенный пример того, как БСП инициализирует длительную операцию на сервере:
// Пример запуска длительной операции через механизмы БСП
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполнения();
ПараметрыВыполнения.НаименованиеФоновогоЗадания = "Закрытие месяца";
Результат = ДлительныеОперации.ВыполнитьВФоне("ЗакрытиеМесяцаСервер.ВыполнитьЗакрытие", ПараметрыЗадания, ПараметрыВыполнения);
Если мы заглянем внутрь программного кода общего модуля ДлительныеОперации, то увидим, что для обеспечения универсальности, обработки ошибок, логирования и передачи контекста БСП выполняет запуск фонового задания через специальный метод-обертку. Фактический вызов на уровне платформы выглядит следующим образом:
// Внутренний вызов платформы в недрах БСП
ФоновыеЗадания.Выполнить("ОбщегоНазначения.ВыполнитьМетодКонфигурации", ПараметрыВызова);
Проанализируем эту ситуацию с точки зрения платформы 1С:
ЗакрытиеМесяцаСервер.ВыполнитьЗакрытие) вы передали внутрь параметров БСП в качестве выполняемого алгоритма.ОбщегоНазначения и его экспортный метод ВыполнитьМетодКонфигурации.BackgroundJob.CommonModule.ОбщегоНазначения.ВыполнитьМетодКонфигурации.Таким образом, если вы пропишете в ТНФ требование для модуля ЗакрытиеМесяцаСервер, оно никогда не сработает, так как платформа физически не видит этот модуль в момент регистрации фонового задания. Если же вы пропишете в ТНФ обертку BackgroundJob.CommonModule.ОбщегоНазначения.ВыполнитьМетодКонфигурации, то на выделенный сервер мгновенно переедет абсолютно весь поток длительных операций системы: формирование любых отчетов, групповое проведение документов, заполнение табличных частей и любые другие фоновые вызовы. Это полностью нарушает саму идею точечного распределения нагрузки.
Рассмотрим подробнее три практических способа решения этой проблемы в зависимости от версии платформы и готовности вносить изменения в конфигурацию.
Это наиболее надежный и архитектурно правильный способ обойти ограничение БСП без грубого вмешательства в типовые механизмы. В отличие от произвольных фоновых заданий, регламентные задания являются полноценными объектами метаданных конфигурации. Они регистрируются платформой напрямую, минуя универсальные обертки БСП, и имеют уникальный постоянный идентификатор.
Разберем по шагам, как реализовать этот подход:
ВыделенноеЗакрытиеМесяца.ЗакрытиеМесяцаСервер.ВыполнитьЗакрытие).ДлительныеОперации.ВыполнитьВФоне() мы будем программно создавать и запускать наше регламентное задание.Посмотрим на пример кода программного вызова:
// Программный запуск регламентного задания из кода
ЗаданиеМетаданные = Метаданные.РегламентныеЗадания.ВыделенноеЗакрытиеМесяца;
НовоеЗадание = РегламентныеЗадания.СоздатьРегламентноеЗадание(ЗаданиеМетаданные);
НовоеЗадание.Наименование = "Выделенный запуск закрытия месяца";
НовоеЗадание.Использование = Истина;
// Передаем параметры, если это необходимо
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(ПараметрыЗапуска);
НовоеЗадание.Параметры = МассивПараметров;
// Записываем и принудительно запускаем задание
НовоеЗадание.Записать();
НовоеЗадание.Выполнить();
Теперь настроим требования назначения функциональности в консоли администрирования кластера серверов 1С (или через утилиту командной строки rac):
Фоновые задания. Дополнительный параметр: BackgroundJob.ScheduledJob.ВыделенноеЗакрытиеМесяца. Выбираем действие: Назначать.Не назначать.Благодаря этому подходу платформа четко идентифицирует регламентное задание по его имени в метаданных и гарантированно перенесет его выполнение на нужный рабочий сервер, не затрагивая другие длительные операции пользователей.
Если вы разрабатываете собственную конфигурацию или глубоко дорабатываете типовую, и вам не требуется сложная интерактивная индикация прогресса выполнения на клиенте, вы можете запустить фоновое задание напрямую стандартным методом платформы ФоновыеЗадания.Выполнить().
Проанализируем, как будет выглядеть программный код запуска в данном сценарии:
// Прямой запуск фонового задания без посредничества БСП
ПараметрыВызова = Новый Массив;
ПараметрыВызова.Добавить(ПараметрыПроцедуры);
НовоеФЗ = ФоновыеЗадания.Выполнить(
"ЗакрытиеМесяцаСервер.ВыполнитьЗакрытие",
ПараметрыВызова,
"УникальныйКлючЗакрытия",
"Тяжелая операция закрытия месяца"
);
В данном случае платформа зарегистрирует фоновое задание с понятным ей и однозначным системным признаком. Теперь мы можем настроить ТНФ в консоли кластера серверов:
Фоновые задания.BackgroundJob.CommonModule.ЗакрытиеМесяцаСервер.ВыполнитьЗакрытие.Назначать (для целевого сервера) и Не назначать (для всех остальных серверов кластера).Важное примечание: При использовании этого метода вам придется самостоятельно обрабатывать жизненный цикл фонового задания на клиенте — проверять его состояние в цикле или через обработчик ожидания, обрабатывать возможные ошибки выполнения и обновлять интерфейс пользователя, так как вы отказываетесь от готового сервисного слоя БСП.
В версии платформы 1С:Предприятие 8.3.27 появился принципиально новый функционал, который позволяет решать подобные проблемы административно, вообще не изменяя программный код конфигурации.
Была реализована возможность распределять клиентские соединения и все связанные с ними фоновые задания (включая запущенные через БСП) по рабочим серверам с помощью специального свойства — Ключа требования назначения (UserAssignmentRuleKey) или по Имени пользователя (UserName).
Рассмотрим, как настроить этот механизм по шагам:
РоботЗакрытияМесяца (или выберем конкретного пользователя, который выполняет эту операцию).HeavyOperationsKey.На выделенном сервере создаем разрешающее требование:
Клиентское соединение с ИБ (Connection).UserAssignmentRuleKey.HeavyOperationsKey (или UserName.РоботЗакрытияМесяца, если привязываемся напрямую к имени пользователя).Назначать.На основном сервере создаем запрещающее требование для этого же ключа или пользователя с действием Не назначать.
Как это работает изнутри? Когда пользователь РоботЗакрытияМесяца инициирует закрытие месяца, его сеанс (клиентское соединение) принудительно переносится на выделенный рабочий сервер кластера согласно правилу ТНФ. Платформа 1С спроектирована так, что все фоновые задания, порожденные этим сеансом (даже если они запущены через универсальную обертку БСП ОбщегоНазначения.ВыполнитьМетодКонфигурации), будут автоматически создаваться и выполняться на том же рабочем сервере, где запущено основное соединение пользователя. Таким образом, мы элегантно решаем проблему изоляции тяжелой нагрузки без переписывания кода БСП.
Для администраторов, предпочитающих автоматизацию через консоль, приведем пример команды для утилиты rac:
# Пример добавления требования через утилиту rac для платформы 8.3.27
rac rule --cluster=00000000-0000-0000-0000-000000000000 --host=server-heavy add --object-type=Connection --action=Apply --filter-type=ExtraParam --filter-value="UserAssignmentRuleKey.HeavyOperationsKey"
Подводя итоги, проанализируем, какой метод лучше выбрать для вашей информационной системы: