Возможно ли использование одного сеанса COM-соединения несколькими пользователями в 1С?

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

В практике интеграции систем на платформе 1С:Предприятие часто возникает вопрос оптимизации ресурсов. Типичный сценарий: есть две базы, и пользователям первой базы необходимо постоянно записывать или считывать данные из второй. Создание отдельного COM-соединения для каждого активного пользователя — процесс ресурсозатратный и медленный, так как инициализация COMConnector может занимать несколько секунд и потреблять значительный объем оперативной памяти. В этой статье мы проанализируем, можно ли «расшарить» одно соединение между всеми пользователями, разберем технические ограничения и найдем архитектурно верные решения.

Почему прямая передача COM-объекта невозможна?

Для начала выясним причину, по которой нельзя просто создать объект COMObject при входе первого пользователя и поместить его в некое общее хранилище (например, в параметры сеанса или в регистр сведений). Проанализируем природу COM (Component Object Model): это технология, основанная на указателях в адресном пространстве конкретного процесса.

COM-объект — это не набор данных, который можно сериализовать (превратить в байты) и передать по сети или сохранить в базу данных. Это «живой» экземпляр в памяти операционной системы. Когда один пользователь создает соединение, оно живет в контексте его сеанса. Попытка поместить этот объект в ХранилищеЗначений приведет к тому, что при извлечении в другом сеансе вы получите пустую ссылку или ошибку, так как в адресном пространстве второго пользователя по этому адресу ничего не существует.

Таким образом, прямой ответ на вопрос: нет, передать сам объект между сеансами нельзя.

Решение через паттерн «Очередь задач» и сеанс-робот

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

Для реализации нам понадобится промежуточное звено. В файловых базах это может быть отдельный запущенный экземпляр 1С («робот»), а в серверных — выделенное фоновое задание.

  1. Создание регистра-очереди: Мы создаем РегистрСведений (например, «ОчередьЗадачCOM»), который будет служить буфером обмена. В нем должны быть поля: ПараметрыЗапроса (тип ХранилищеЗначений), Статус (Новый, ВРаботе, Выполнено, Ошибка), Результат (тип ХранилищеЗначений).
  2. Инициализация соединения: Выделенный сеанс (робот) при запуске один раз создает COMConnector и авторизуется в базе-приемнике. Он держит это соединение открытым в глобальной переменной или в модуле.
  3. Постановка задачи пользователем: Когда обычному пользователю нужно создать документ во второй базе, он не вызывает COM. Он записывает новую строку в РегистрСведений, упаковывая данные документа (структуру) в ХранилищеЗначений.
  4. Обработка очереди: Сеанс-робот в цикле (через ОбработчикОжидания) проверяет наличие новых записей в регистре. Найдя задачу, он берет свое «прогретое» соединение, выполняет операцию в базе 2, получает результат и записывает его обратно в регистр, меняя статус на «Выполнено».
  5. Получение результата: Пользовательская форма в это время может ожидать появления результата, периодически опрашивая регистр.

Рассмотрим пример кода для постановки задачи пользователем:


ДанныеДляПередачи = Новый Структура;
ДанныеДляПередачи.Вставить("Дата", ТекущаяДата());
ДанныеДляПередачи.Вставить("Контрагент", Объект.Контрагент.Наименование);

НоваяЗапись = РегистрыСведений.ОчередьЗадачCOM.СоздатьМенеджерЗаписи();
НоваяЗапись.ID = Строка(Новый УникальныйИдентификатор());
НоваяЗапись.ПараметрыЗапроса = Новый ХранилищеЗначений(ДанныеДляПередачи);
НоваяЗапись.Статус = Перечисления.СтатусыЗадач.Новый;
НоваяЗапись.Записать();

Проблемы стабильности и утечек памяти

Проанализируем ситуацию с длительным использованием одного COM-соединения. У этого подхода есть существенные технические риски, которые необходимо учитывать при разработке:

Современная и надежная альтернатива: HTTP-сервисы

Выясним причину, по которой опытные разработчики советуют отказываться от COM в пользу HTTP-сервисов. COM-соединение требует наличия установленной платформы той же версии на клиентской машине, регистрации библиотек comcntr.dll и прав администратора. Это «хрупкая» технология.

Разберем, как решить задачу автора через HTTP-протокол:

  1. База-приемник: В ней создается объект HTTP-сервис. Мы описываем шаблоны URL и методы (POST, GET).
  2. База-источник: Вместо COM используется объект HTTPСоединение.
  3. Пул соединений: Если база-приемник опубликована на веб-сервере (IIS или Apache), то сам веб-сервер берет на себя задачу управления очередью и пулом соединений. Это работает в десятки раз быстрее и стабильнее, чем COM.

Пример обращения к HTTP-сервису вместо COM:


Соединение = Новый HTTPСоединение("server.com", , "admin", "password");
Запрос = Новый HTTPЗапрос("/base2/hs/v1/create_doc");
Запрос.УстановитьТелоИзСтроки(ДанныеВФорматеJSON);
Ответ = Соединение.ВызватьHTTPМетод("POST", Запрос);

Если Ответ.КодСостояния = 200 Тогда
    // Обрабатываем успех
КонецЕсли;

Работа в 64-битных системах (COM+)

Если вы все же решили использовать COM на серверной 64-битной платформе, вы столкнетесь с тем, что 64-битный процесс сервера не может загрузить 32-битный COM-компонент (если версии разнятся). В этом случае проанализируем настройку через Службы компонентов (COM+).

Создание «обертки» в COM+ позволяет вынести COM-соединение в отдельный процесс операционной системы (dllhost.exe). Это дает дополнительный плюс к отказоустойчивости: если COM-соединение критически ошибется и «упадет», основной рабочий процесс сервера 1С останется жив. Это своего рода изоляция, которая позволяет реализовать подобие пула соединений на уровне ОС.

Резюме

Подведем итог: использовать один и тот же программный объект COMObject в разных сеансах невозможно из-за ограничений архитектуры Windows и 1С. Однако задачу совместного использования ресурсов можно решить через паттерн очереди в информационной базе или (что более правильно) через переход на HTTP/REST интерфейсы. Это избавит вас от проблем с регистрацией библиотек, утечками памяти и сложностями отладки.

← На главную