Как и где правильно хранить COM-соединение в управляемых формах 1С?

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

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

Почему COM-соединение нельзя сохранить в реквизитах или временном хранилище

Проанализируем базовую причину сложностей при попытке сохранить объект COM-объект между серверными вызовами управляемой формы:

  1. Несериализуемость объекта: Объект COM-соединения является неуправляемым системным указателем операционной системы на память процесса. Платформа 1С не может преобразовать его в поток байтов (сериализовать), поэтому попытка поместить его во ВременноеХранилище, ХранилищеЗначения или сохранить в реквизит формы вызовет ошибку выполнения.
  2. Многопроцессная архитектура кластера: В клиент-серверном варианте последовательные серверные вызовы из одной и той же клиентской формы могут обрабатываться разными рабочими процессами rphost.exe. Передать COM-указатель из памяти одного процесса в память другого невозможно.
  3. Зависание сеансов и утечки памяти: Если удерживать открытое COM-соединение неограниченно долго, в целевой базе блокируется клиентская лицензия и расходуется сеанс, а сборщик мусора платформы может несвоевременно освобождать COM-интерфейсы, приводя к росту потребления памяти.

Вариант 1. Использование функции с повторным использованием возвращаемых значений

Если конфигурация доступна для редактирования, для кэширования соединения в рамках одного серверного процесса можно использовать общий модуль со свойством Повторное использование возвращаемых значений (на время сеанса или на время вызова).

Рассмотрим, как работает данный механизм: первый вызов серверной функции выполняет подключение и возвращает ссылку на COM-объект, а последующие вызовы возвращают уже готовый результат из оперативной памяти процесса без повторной авторизации.


// Функция в общем модуле с повторным использованием (На время сеанса)
Функция ПолучитьСоединениеСВнешнейБазой() Экспорт
    
    ПараметрыПодключения = "Srvr=""server1c"";Ref=""trade_db"";Usr=""ExchangeUser"";Pwd=""Password123"";";
    
    V83 = Новый COMОбъект("V83.COMConnector");
    Соединение = V83.Connect(ПараметрыПодключения);
    
    Возврат Соединение;
    
КонецФункции

Обратим внимание на особенности этого способа: кэш привязан к конкретному рабочему процессу rphost. Если балансировщик кластера перенаправит очередной серверный вызов на другой рабочий процесс или произойдет сброс кэша платформой, функция просто отработает заново и инициализирует новое соединение.

Вариант 2. Хранение COM-объекта в контексте клиента

Если работа с внешним источником или файловой базой инициируется непосредственно с рабочего места пользователя (например, при вызове локальных драйверов или компонентов), COM-объект можно сохранить в модуле формы на клиенте с помощью директивы Перем.


&НаКлиенте
Перем ЛокальныйКоннектор;

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    // Инициализируем коннектор при открытии формы
    V83 = Новый COMОбъект("V83.COMConnector");
    ЛокальныйКоннектор = V83.Connect("File=""C:\Bases\ExchangeDB"";Usr=""Admin"";Pwd="""";");
    
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьОперацию()
    
    Если ЛокальныйКоннектор = Неопределено Тогда
        // Восстановление при разрыве соединения
        V83 = Новый COMОбъект("V83.COMConnector");
        ЛокальныйКоннектор = V83.Connect("File=""C:\Bases\ExchangeDB"";Usr=""Admin"";Pwd="""";");
    КонецЕсли;
    
    // Вызов методов внешней базы
    ВнешнийСправочник = ЛокальныйКоннектор.Справочники.Номенклатура;
    
КонецПроцедуры

&НаКлиенте
Процедура ПриЗакрытии(ЗавершениеРаботы)
    
    // Явное освобождение ресурса при закрытии формы
    ЛокальныйКоннектор = Неопределено;
    
КонецПроцедуры

Важно помнить: клиентскую переменную невозможно напрямую передать в контекст &НаСервере. Если основные вычисления должны происходить на сервере, этот вариант не применяется.

Вариант 3. Выполнение операций «по требованию» в рамках одной серверной процедуры

Наиболее надежный и стабильный подход в управляемом приложении — не удерживать постоянное соединение в фоновом режиме, а устанавливать его строго на время выполнения пакетной обработки данных с последующим обязательным закрытием.

Посмотрим на пример организации серверного кода:


&НаСервере
Процедура ПолучитьДанныеИзВнешнейБазыНаСервере()
    
    ПараметрыПодключения = "Srvr=""app-srv"";Ref=""accounting"";Usr=""Robot"";Pwd=""Secret"";";
    
    Попытка
        V83 = Новый COMОбъект("V83.COMConnector");
        Соединение = V83.Connect(ПараметрыПодключения);
    Исключение
        ВызватьИсключение "Ошибка подключения к внешней базе: " + ОписаниеОшибки();
    КонецПопытки;
    
    Попытка
        // Выполняем все необходимые действия в рамках одного вызова
        ВыгрузитьКадровыеДанные(Соединение);
        ВыгрузитьСкладскиеОстатки(Соединение);
    Исключение
        // Обязательно освобождаем ресурс даже при ошибке обработки
        Соединение = Неопределено;
        ВызватьИсключение;
    КонецПопытки;
    
    // Завершаем работу соединения и освобождаем лицензию
    Соединение = Неопределено;
    
КонецПроцедуры

Архитектурные альтернативы использованию COMConnector

При проектировании современных систем на платформе 1С:Предприятие 8.3 рекомендуется избегать длительных COM-соединений по следующим причинам:

  1. Переход на HTTP-сервисы и REST API: Веб- и HTTP-сервисы работают по стандарту без удержания клиентских лицензий, поддерживают пулинг сетевых соединений на уровне веб-сервера и корректно функционируют на серверах под управлением Linux.
  2. Фоновые задания и длительные операции: Для внешних отчетов и тяжелых выгрузок получение данных из внешних систем следует выносить в фоновые потоки. Внутри фонового задания создается коннектор, данные считываются в универсальную таблицу значений, после чего соединение уничтожается, а результат передается в форму через временное хранилище.
  3. Кэширование промежуточных данных: Если данные из внешней базы запрашиваются регулярно в течение сеанса пользователя, эффективнее один раз запросить таблицу значений и сохранить ее в реквизите формы или временном хранилище, обращаясь к внешнему соединению только при отсутствии требуемого периода в кэше.
← На главную