Где и как хранить COM-соединение в 1С для ускорения обмена данными?

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

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

Вариант 1. Экспортная переменная в Модуле обычного приложения

В толстом клиенте обычного приложения наиболее прямолинейным способом повторного использования является размещение объекта в глобальной переменной. Память толстого клиента принадлежит процессу 1cv8.exe, и созданный COM-объект будет жить на протяжении всего сеанса работы пользователя.

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

Посмотрим на пример организации глобальной переменной и функции получения соединения в МодулеОбычногоПриложения:


Перем глCOMСоединение Экспорт;

Функция ПолучитьCOMСоединение() Экспорт
    Если глCOMСоединение <> Неопределено Тогда
        Попытка
            // Проверяем доступность базы через легкое обращение к метаданным
            ИмяБазы = глCOMСоединение.Метаданные.Имя;
            Возврат глCOMСоединение;
        Исключение
            // Соединение разорвано или "протухло", очищаем переменную
            глCOMСоединение = Неопределено;
        КонецПопытки;
    КонецЕсли;

    Попытка
        Коннектор = Новый COMОбъект("V83.COMConnector");
        СтрокаПодключения = "Srvr=""Server1C"";Ref=""TargetBase"";Usr=""ExchangeUser"";Pwd=""SecretPass"";";
        глCOMСоединение = Коннектор.Connect(СтрокаПодключения);
    Исключение
        глCOMСоединение = Неопределено;
        ВызватьИсключение "Ошибка подключения к удаленной базе: " + ОписаниеОшибки();
    КонецПопытки;

    Возврат глCOMСоединение;
КонецФункции

Важное правило работы с памятью: каждый объект, полученный из внешнего соединения (выборка, ссылка или таблица значений), удерживает память на стороне удаленного сервера. При использовании постоянного соединения обязательно зануляйте промежуточные переменные (Объект = Неопределено;) сразу после окончания их обработки, иначе возникнут серьезные утечки оперативной памяти.

Ограничения платформы: почему не подходят параметры сеанса и временное хранилище

Проанализируем распространенные заблуждения касательно того, где еще можно разместить COM-объект:

  1. Параметры сеанса: сохранить объект COMОбъект напрямую или внутри структуры/массива в параметре сеанса невозможно. Платформа 1С требует, чтобы все значения параметров сеанса поддерживали XDTO-сериализацию. Указатели COM не сериализуются, при попытке записи возникнет ошибка несоответствия типов.
  2. Временное хранилище и клиент-серверные границы: соединение COM привязано к адресному пространству конкретного процесса операционной системы (клиентского 1cv8.exe или серверного rphost). Передать активный COM-указатель между клиентом и сервером или выгрузить во временное хранилище для другого потока нельзя.

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

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

Выясним особенности этого механизма:

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

Архитектурная проблема: COM-соединение в транзакции проведения

Попытка вызывать внешнее соединение в обработчике ОбработкаПроведения или из модуля формы документа несет критические риски для стабильности базы данных:

  1. Транзакционные блокировки и зависания: пока выполняется сетевой запрос к внешней базе, локальная транзакция проведения удерживает блокировки на таблицы регистров. Если внешняя база медленно отвечает или в ней возникли блокировки, все остальные пользователи исходной базы будут заблокированы при попытке провести свои документы.
  2. Взаимоблокировки (Deadlocks): при двусторонних обменах синхронные вызовы между двумя базами почти гарантированно приводят к неразрешимым взаимоблокировкам.

Вариант 3. Переход на асинхронную очередь (Регистр сведений + Регламентное задание)

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

  1. Создаем непериодический регистр сведений ОчередьИсходящихСообщений с измерением Документ (или СсылкаНаОбъект) и ресурсом ДатаРегистрации.
  2. В модуле документа внутри транзакции проведения выполняется только мгновенная запись в этот регистр.
  3. Отдельное фоновое или регламентное задание по расписанию (например, раз в 1–2 минуты) считывает пачку записей из регистра, открывает COM-соединение, переносит данные во внешнюю базу и удаляет обработанные строки.

Посмотрим на пример логики регламентного задания, обрабатывающего очередь пакетами:


Процедура ВыполнитьОтправкуОчереди() Экспорт
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 50
        |    Очередь.Документ КАК Документ
        |ИЗ
        |    РегистрСведений.ОчередьИсходящихСообщений КАК Очередь
        |УПОРЯДОЧИТЬ ПО
        |    Очередь.ДатаРегистрации ВОЗР";
    
    Результат = Запрос.Выполнить();
    Если Результат.Пустой() Тогда
        Возврат;
    КонецЕсли;
    
    // Инициализируем соединение один раз на весь пакет
    Соединение = ПолучитьCOMСоединение();
    Выборка = Результат.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        Попытка
            // Передаем данные во внешнюю базу через Соединение
            // ... логика передачи ...
            
            // Удаляем запись из очереди после успешной передачи
            НаборЗаписей = РегистрыСведений.ОчередьИсходящихСообщений.СоздатьНаборЗаписей();
            НаборЗаписей.Отбор.Документ.Установить(Выборка.Документ);
            НаборЗаписей.Записать();
        Исключение
            // Фиксируем ошибку и прерываем пачку, чтобы не терять данные
            ЗаписьЖурналаРегистрации("Интеграция COM", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
            Прервать;
        КонецПопытки;
    КонецЦикла;
КонецПроцедуры

Вариант 4. Настройка пула соединений через COM+ (Службы компонентов Windows)

Если отказаться от синхронных вызовов невозможно, время на инициализацию можно существенно сократить на уровне операционной системы, настроив пул объектов COM+:

  1. Откройте оснастку Службы компонентов (dcomcnfg) на сервере Windows.
  2. Создайте новое серверное приложение COM+ и добавьте в него библиотеку comcntr.dll из каталога установленной платформы 1С.
  3. В свойствах компонента включите Пул объектов (Object Pooling) и укажите минимальный и максимальный размер пула.
  4. Это позволяет операционной системе держать готовые экземпляры коннекторов в системном процессе dllhost.exe, ускоряя повторные подключения и изолируя адресное пространство основного процесса 1С.

Вариант 5. Переход на HTTP-сервисы и Web-сервисы

В долгосрочной перспективе рекомендуется полностью заменить COM-технологию на стандартные веб-протоколы (HTTP / REST или SOAP / WS):

  1. Веб-сервисы не требуют установки одинаковой разрядности компонентов на стороне клиента и сервера.
  2. Обработка HTTP-запроса платформой 1С происходит в готовом пуле сеансов веб-расширения, обеспечивая высокую скорость ответа без накладных расходов на старт тяжелых COM-сессий.
  3. Архитектура становится платформонезависимой и масштабируемой.
← На главную