Модуль менеджера в 1С 8.3: на какой стороне работает его код

· 9 мин

Содержание

Код модуля менеджера в 1С 8.3 выполняется на сервере. В клиент-серверном варианте это рабочий процесс rphost на машине кластера 1С, в файловом — серверная часть внутри процесса клиента или веб-сервера. Из тонкого и веб-клиента модуль менеджера напрямую недоступен; исключение — толстый клиент в режиме обычного приложения и внешнее соединение.

Типичная ситуация: программист пишет в модуле менеджера документа функцию ПолучитьОстатки(), вызывает её из обработчика кнопки формы с директивой &НаКлиенте — и конфигуратор не даёт сохранить модуль. Или функция сохраняет файл в КаталогВременныхФайлов(), а пользователь не находит его на своём компьютере: файл лёг на диск сервера. Обе проблемы — от непонимания, где на самом деле крутится код.

Как устроена клиент-серверная архитектура платформы 1С 8.3

Любая конфигурация 1С 8.3 делит код на две стороны: клиентскую и серверную. Клиент отвечает за интерфейс: формы, диалоги, реакцию на кнопки. Сервер — за работу с данными: запросы, запись объектов, проведение, блокировки.

Между ними идёт обмен вызовами. Каждый переход с клиента на сервер — это сетевой запрос, сериализация параметров и ожидание ответа. Поэтому платформа строго следит, какой код где может работать.

Модули конфигурации по месту выполнения делятся так:

  • 🖥️ Только сервер — модуль менеджера, модуль объекта, модуль набора записей, модуль менеджера значения, серверные общие модули.
  • 💻 Только клиент — модуль управляемого приложения, клиентские общие модули.
  • 🔀 Обе стороны — модуль формы (по директивам &НаКлиенте, &НаСервере и т. д.), общие модули с несколькими флагами компиляции.

У модуля менеджера нет директив компиляции для отдельных процедур. Весь модуль собирается в одном контексте — серверном (плюс толстый клиент обычного приложения и внешнее соединение, о них ниже).

Что обычно пишут в модуле менеджера

  • 📄 обработчики ОбработкаПолученияФормы, ОбработкаПолученияДанныхВыбора, ОбработкаПолученияПредставления;
  • 🖨️ процедуры печатных форм и команд печати;
  • 🔎 экспортные функции, которые работают со всем набором объектов: выборки, проверки, служебные расчёты;
  • 🔄 обработчики обновления данных при переходе на новую версию конфигурации.

Всё это код, которому нужен доступ к базе, — значит, и место ему на сервере.

Где физически выполняется модуль менеджера: сервер, кластер, процессы

В клиент-серверном варианте сервер 1С — это не одна программа, а набор процессов, объединённых в кластер.

ПроцессЧто делаетВыполняет ли код модуля менеджера
ragentагент сервера, служба Windows или демон Linux, точка входа для консоли администрированиянет
rmngrменеджер кластера: хранит реестр кластера, распределяет сеансы, ведёт блокировкинет
rphostрабочий процесс: исполняет серверный код и отправляет запросы в СУБДда

Не путайте модуль менеджера (объект конфигурации) и менеджер кластера rmngr (процесс сервера). Это разные вещи с похожими названиями. Ваш код из модуля менеджера документа исполняется в rphost, а rmngr лишь решает, на какой рабочий процесс отправить сеанс.

Как распределяется нагрузка

  • ⚙️ В кластере может быть несколько рабочих серверов и несколько процессов rphost на каждом.
  • 🔁 Один сеанс пользователя может обслуживаться разными рабочими процессами в разные моменты — процесс не закреплён за пользователем навсегда.
  • 🧵 Из-за этого переменные модуля менеджера не хранят состояние между серверными вызовами. Что нужно сохранить — кладите в реквизиты формы, параметры сеанса или в базу.

Фоновые задания тоже идут в rphost. Если из модуля менеджера запустить ФоновыеЗадания.Выполнить() с экспортной процедурой этого же модуля, код уйдёт в отдельный фоновый сеанс на сервере кластера.

Серверный контекст и клиентский: в чём разница для модуля менеджера

Серверный контекст даёт доступ к тому, чего на клиенте нет:

  • 🗄️ менеджеры объектов: Документы, Справочники, РегистрыНакопления и другие;
  • 📊 объект Запрос и работа с выборками;
  • ✍️ методы Записать(), Удалить(), проведение документов;
  • 🔒 управляемые блокировки, транзакции, привилегированный режим.

И наоборот, на сервере нет интерактива. Нельзя открыть форму, показать ПоказатьВопрос(), выбрать файл на диске пользователя. Сообщить() и ОбщегоНазначения.СообщитьПользователю() из серверного кода работают: сообщения доставятся клиенту, когда вызов вернётся.

Как вызвать модуль менеджера из формы

Из клиентской процедуры формы к модулю менеджера идут через серверный метод:

&НаКлиенте
Процедура ЗаполнитьОстатки(Команда)
	ЗаполнитьОстаткиНаСервере();
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьОстаткиНаСервере()
	Таблица = Документы.ПоступлениеТоваровУслуг.ОстаткиПоСкладу(Объект.Склад);
	Объект.Товары.Загрузить(Таблица);
КонецПроцедуры

Функция ОстаткиПоСкладу в модуле менеджера должна быть объявлена с ключевым словом Экспорт, иначе снаружи модуля её не видно.

Если вызов нужен из клиентского общего модуля, делают промежуточный общий модуль с флагами «Сервер» и «Вызов сервера» и уже из него обращаются к менеджеру.

Если форма уже на сервере (&НаСервере), лучше &НаСервереБезКонтекста для вызова, которому не нужны данные формы. Он не передаёт на сервер всю форму целиком и работает быстрее.

Как проверить, где выполняется операция

Когда непонятно, на какой стороне сработал код, есть несколько способов проверить.

Способ 1. Инструкции препроцессора

Простая вставка показывает контекст прямо в сообщении:

#Если Сервер Тогда
	Сообщить("Сервер: " + ИмяКомпьютера());
#ИначеЕсли ТолстыйКлиентОбычноеПриложение Тогда
	Сообщить("Толстый клиент: " + ИмяКомпьютера());
#ИначеЕсли ВнешнееСоединение Тогда
	Сообщить("Внешнее соединение");
#КонецЕсли

ИмяКомпьютера() возвращает имя машины, на которой исполняется код. В клиент-серверном варианте из модуля менеджера вы увидите имя рабочего сервера кластера, а не компьютера пользователя.

Способ 2. Отладчик

В отладчике конфигуратора сразу видно, в каком предмете отладки остановилась точка: клиент, сервер, фоновое задание.

Для серверной отладки в клиент-серверном варианте нужно, чтобы служба агента сервера была запущена с ключом -debug. Иначе точки останова в модуле менеджера просто не сработают — ошибки не будет, код выполнится молча.

Чтобы добавить ключ -debug, службу агента сервера придётся перезапустить. Все сеансы пользователей на этом сервере оборвутся. Делайте это вне рабочего времени или на тестовом сервере.

Способ 3. Замер производительности

Замер производительности в отладчике показывает, какие строки выполнились на клиенте, а какие на сервере, и сколько было серверных вызовов. Это лучший способ найти лишние переходы клиент → сервер в цикле.

Способ 4. Технологический журнал

На сервере кластера можно включить технологический журнал через файл logcfg.xml. События CALL и SCALL покажут серверные вызовы с указанием модуля и метода. Способ тяжёлый, его оставляют для разбора проблем производительности на рабочей базе.

Файловая база и клиент-серверная: как вариант работы влияет на выполнение

Код один и тот же, но физическое место выполнения меняется.

Файловый вариант

Отдельного сервера 1С нет. Серверная часть платформы работает внутри процесса клиента:

  • 💻 тонкий клиент (1cv8c) с файловой базой — серверный код исполняется на компьютере пользователя, в том же процессе;
  • 🌐 веб-клиент через публикацию — серверный код исполняется в процессе веб-сервера (Apache или IIS) с модулем расширения 1С;
  • 🗂️ данные читаются напрямую из файла 1Cv8.1CD.

Разделение клиент/сервер при этом сохраняется на уровне языка. Директивы работают так же, вызов модуля менеджера с клиента запрещён так же. Поэтому конфигурация, написанная в файловом режиме, без переделок переносится на сервер 1С.

Ловушка файлового варианта: код с ошибкой контекста иногда «работает» при отладке на файловой базе, потому что клиент и сервер — один компьютер. Например, путь C:\Выгрузка из серверного кода существует. После переноса на кластер тот же путь будет искаться уже на диске сервера.

Клиент-серверный вариант

Серверный код идёт в rphost на сервере 1С. Запросы из модуля менеджера переводятся в SQL и уходят в СУБД.

Конкретная СУБД — MS SQL Server, PostgreSQL, IBM Db2 или Oracle Database — не меняет место выполнения кода. СУБД исполняет только запросы, а не встроенный язык. От неё зависят скорость, поведение блокировок и некоторые ограничения языка запросов, но не то, где работает модуль менеджера.

Сводная таблица контекстов выполнения

Режим работыГде исполняется код модуля менеджераДоступен ли модуль менеджера напрямую с клиента
Тонкий клиент + сервер 1Сrphost на сервере кластеранет, только через серверный вызов
Тонкий клиент + файловая базапроцесс 1cv8c на компьютере пользователянет, только через серверный вызов
Веб-клиентrphost (кластер) или процесс веб-сервера (файловая база)нет
Толстый клиент, управляемое приложениекак у тонкого: на серверенет
Толстый клиент, обычное приложениев процессе толстого клиента на компьютере пользователя или на сервере — смотря откуда вызванда
Внешнее соединение (COM)в процессе внешнего соединенияда
Фоновое задание, регламентное заданиеrphost, отдельный фоновый сеанс—
Мобильный клиентна сервере, к которому он подключённет

Режим обычного приложения в толстом клиенте — наследие 8.1 и 8.2. Там модули объектов и менеджеров компилируются и на клиенте. Поэтому в типовых конфигурациях модули менеджеров часто обёрнуты в такую конструкцию:

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

// процедуры и функции модуля менеджера

#Иначе
ВызватьИсключение НСтр("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли

Это защита: если кто-то попытается использовать модуль в недопустимом контексте, он получит понятное исключение, а не странное поведение.

Как у вас запускается код, который обращается к модулю менеджера?

Типичные ошибки распределения кода между клиентом и сервером

Ошибка 1. Обращение к менеджеру из клиентской процедуры

Строка Документы.РеализацияТоваровУслуг.ПечатьНакладной() в процедуре &НаКлиенте не пройдёт проверку модуля: свойство глобального контекста Документы на клиенте не определено. Решение — серверный вызов, как в примере выше.

Ошибка 2. Серверный вызов в цикле

Клиентский цикл по 500 строкам табличной части, в котором для каждой строки вызывается серверная функция, даёт 500 сетевых обращений. На медленном канале это минуты ожидания.

Правильно — собрать данные в массив, передать на сервер один раз, обработать там одним запросом и вернуть результат.

Ошибка 3. Файлы «пропадают»

Код модуля менеджера, который пишет файл через ТекстовыйДокумент.Записать() или ТабличныйДокумент.Записать(), сохраняет его на диск сервера. Чтобы отдать файл пользователю, его помещают во временное хранилище (ПоместитьВоВременноеХранилище()), а на клиенте получают методом ПолучитьФайл() или НачатьПолучениеФайлаССервера().

Ошибка 4. Время сервера вместо времени пользователя

ТекущаяДата() в модуле менеджера вернёт время компьютера, на котором выполняется код, — то есть сервера. Если сервер и пользователи в разных часовых поясах, используйте ТекущаяДатаСеанса(): она учитывает часовой пояс сеанса.

Ошибка 5. Передача объекта на клиент

ДокументОбъект и СправочникОбъект нельзя вернуть из серверной функции на клиент. Возвращайте ссылку, структуру с нужными полями или используйте ДанныеФормыВЗначение() и ЗначениеВДанныеФормы() при работе с формой объекта.

Ошибка 6. Ожидание, что модуль менеджера «помнит» данные

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

Частые вопросы

Выполняются ли права пользователя в модуле менеджера?
Да. Код модуля менеджера работает с правами текущего пользователя сеанса. Чтобы выполнить операцию без проверки прав, нужен привилегированный режим: УстановитьПривилегированныйРежим(Истина) или серверный общий модуль с флагом «Привилегированный».
Можно ли вызвать модуль менеджера из расширения конфигурации?
Можно. Расширение умеет добавлять в модуль менеджера свои процедуры и перехватывать существующие через аннотации &Перед, &После, &Вместо. Контекст выполнения остаётся тем же — серверным.
Чем модуль менеджера отличается от модуля объекта по месту выполнения?
Ничем: оба серверные. Разница в назначении. Модуль объекта работает с одним экземпляром (событиями ПередЗаписью, ОбработкаПроведения), модуль менеджера — с типом объекта в целом.
Где выполняется модуль менеджера при работе через HTTP-сервис или веб-сервис?
На сервере 1С. Обработчик HTTP- или веб-сервиса сам по себе серверный, поэтому к модулю менеджера из него обращаются напрямую.
Влияет ли количество рабочих процессов на работу модуля менеджера?
На логику — нет, на скорость — да. Чем больше процессов и серверов в кластере, тем лучше распределяются одновременные вызовы. Код должен быть написан так, чтобы не зависеть от того, какой rphost его выполнит.