Как эффективно управлять передачей данных между клиентом и сервером в 1С:Предприятии?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← К списку

При разработке в 1С:Предприятии мы часто сталкиваемся с необходимостью выполнения кода на сервере из клиентской части приложения. Для этого используются специальные директивы, такие как &НаСервере и &НаСервереБезКонтекста. Разберем подробно, в чем заключается их отличие, как это влияет на производительность и как мы можем оптимизировать работу наших приложений.

Что такое "контекст формы" и как он передается?

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

Когда мы вызываем серверную процедуру или функцию из клиентской части формы с директивой &НаСервере, происходит целый процесс:

  1. Упаковка контекста: Система "упаковывает" весь контекст формы, преобразуя данные платформы 1С в формат XML. Этот процесс называется XML-сериализацией.
  2. Передача на сервер: Упакованный контекст передается на сервер.
  3. Разворачивание на сервере: На сервере происходит "разворачивание" полученного контекста, инициализация методов формы и серверной копии данных формы.
  4. Выполнение кода: Выполняется наш серверный код.
  5. Обратная упаковка и передача: После выполнения кода, измененный контекст формы снова упаковывается и передается обратно на клиент.
  6. Синхронизация на клиенте: На клиенте происходит синхронизация — полученный с сервера контекст заменяет текущий клиентский контекст формы.

Мы видим, что это достаточно сложный и многоступенчатый процесс, который может быть весьма затратным, особенно если контекст формы содержит большой объем данных.

Разбираем различия: &НаСервере против &НаСервереБезКонтекста

Основное различие между этими двумя директивами заключается в том, какой объем данных передается на сервер и какой доступ к данным формы имеет серверная процедура.

  1. Вызов &НаСервере (контекстный)

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

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

    Рассмотрим пример:

    
    &НаСервере
    Процедура ОбработатьДанныеФормыНаСервере()
        // Здесь мы имеем доступ ко всем реквизитам формы
        // Например, к реквизиту "ТекстовоеПоле"
        Если Не ЗначениеЗаполнено(ТекстовоеПоле) Тогда
            Сообщить("Текстовое поле не заполнено!");
            Возврат;
        КонецЕсли;
        // Выполняем действия с данными формы
        РезультатОбработки = "Данные обработаны: " + ТекстовоеПоле;
    КонецПроцедуры
    
  2. Вызов &НаСервереБезКонтекста (внеконтекстный)

    При внеконтекстной передаче управления на сервер передаются только те данные, которые мы явно указали в параметрах процедуры или функции. Доступа к контексту формы (реквизитам, параметрам, элементам) у такой процедуры или функции на сервере нет. Это означает, что мы не можем обратиться напрямую к ТекстовоеПоле или Элементы.МояТаблица внутри такой процедуры.

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

    Посмотрим на пример:

    
    &НаСервереБезКонтекста
    Процедура ВыполнитьОперациюБезКонтекста(Параметр1, Параметр2)
        // Здесь у нас есть доступ только к Параметр1 и Параметр2
        // Обращение к реквизитам формы, например, ТекстовоеПоле, вызовет ошибку
        Результат = Параметр1 + Параметр2;
        // ... выполняем другие действия, не требующие контекста формы
        СообщитьНаКлиенте("Результат операции: " + Результат);
    КонецПроцедуры
    
    // Вызов с клиента:
    // ВыполнитьОперациюБезКонтекста(МойРеквизит1, МойРеквизит2);
    

Производительность: Мы уже упоминали, что контекстный вызов — это довольно затратный процесс. Он включает упаковку, передачу, разворачивание контекста на сервере, выполнение кода, а затем обратную упаковку, передачу и синхронизацию на клиенте. Внеконтекстные вызовы, напротив, значительно уменьшают объем передаваемых данных и, как следствие, нагрузку на сеть и сервер, что приводит к повышению производительности.

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

Практические рекомендации по оптимизации передачи данных

Для того чтобы наши приложения работали быстро и стабильно, нам необходимо придерживаться определенных принципов оптимизации:

  1. Минимизация серверных вызовов

    Каждый серверный вызов, даже если он передает небольшой объем данных, требует времени на установление соединения, передачу служебной информации и обработку. Мы можем столкнуться с задержками, например, до 1,5 секунд при работе тонкого клиента через медленные каналы связи (GPRS). Поэтому стремитесь минимизировать количество серверных вызовов, инициируемых нашим кодом. Объединяйте несколько небольших операций в один серверный вызов, если это возможно.

  2. Уменьшение объема передаваемых данных

    Это одна из ключевых стратегий. Мы уже выяснили, что &НаСервереБезКонтекста помогает в этом. Кроме того, мы можем:

    • Передавать информацию по требованию: Не загружайте все данные сразу. Загружайте только те данные, которые необходимы в данный момент.
    • Передавать данные порциями: Если объем данных все же большой, старайтесь передавать их частями, чтобы не перегружать канал связи и сервер одним большим пакетом.
  3. Кэширование

    Система 1С использует многоуровневое кэширование (в пределах сеанса и в пределах формы). Это означает, что платформа запоминает полученную информацию и не передает её повторно при аналогичных вызовах в том же сеансе или для той же формы. Мы должны учитывать это при проектировании наших решений, чтобы не запрашивать одни и те же данные многократно.

  4. Работа с большими объемами данных

    • Если на сервере требуется обращаться к большому массиву данных, хранящихся в данных формы, то иногда выгоднее выполнить контекстный серверный вызов, так как платформа может эффективно выполнить передачу данных формы, используя свои внутренние оптимизации.
    • При передаче очень больших объемов данных (превышающих 4 Гб за вызов во временное хранилище) могут возникнуть проблемы. В таких случаях мы можем использовать функции глобального контекста РазделитьФайл() и ОбъединитьФайлы() для разбиения файла на части и последующей их сборки.
    • При помещении данных во временное хранилище активно используются временные файлы, и может потребоваться четырехкратный объем дискового пространства относительно размера помещаемого файла. Учитывайте это при работе с файлами большого размера.
    • Для передачи очень больших файлов по защищенным протоколам, когда встроенные средства 1С не подходят, мы можем рассмотреть использование внешних компонент или утилит.
  5. Использование инструментов профилирования и мониторинга

    Для выявления "узких мест" и оценки производительности наших решений крайне важно использовать профилировщик кода и инструменты мониторинга. Технологический журнал 1С также может предоставить ценную информацию о суммарном времени выполнения запросов и серверных вызовов, помогая нам понять, где именно возникают задержки.

  6. Архитектурный подход

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

Как "пощупать" эффект передачи контекста?

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

  1. Создайте объемный реквизит: В форме создайте реквизит типа "Строка" неограниченной длины. На клиентской стороне заполните его очень длинной, случайной (несжимаемой) строкой, например, длиной в сотни мегабайт или даже гигабайт.
  2. Вызовите &НаСервере: Создайте процедуру, которая вызывается с директивой &НаСервере. Внутри этой процедуры не обязательно что-то делать с нашим объемным реквизитом, достаточно самого факта его передачи.
  3. Вызовите &НаСервереБезКонтекста: Создайте другую процедуру с директивой &НаСервереБезКонтекста, которая не принимает наш объемный реквизит в качестве параметра.
  4. Используйте инструменты мониторинга: Запустите 1С в режиме отладки или используйте технологический журнал. Отслеживайте сетевой трафик, загрузку процессора и потребление памяти процессом сервера 1С (ragent.exe, rmngr.exe, rphost.exe) в диспетчере задач или специализированных утилитах.

Вы заметите, что одиночные вызовы &НаСервере или &НаСервереБезКонтекста могут не показать существенной разницы, так как накладные расходы на каждый вызов и резервирование памяти могут скрыть эффект. Однако, если мы будем выполнять эти вызовы в цикле (например, 100-1000 раз), то разница станет очевидной. При циклическом вызове &НаСервере вы увидите значительное увеличение сетевого трафика и, возможно, заметный рост потребления памяти серверным процессом, а также заметите существенное снижение скорости выполнения по сравнению с &НаСервереБезКонтекста.

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

← К списку