Как использовать единожды инициализированную на сервере внешнюю компоненту для разных пользователей?

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

В процессе разработки высоконагруженных систем на базе 1С:Предприятие программисты часто сталкиваются с проблемой "тяжелых" внешних компонентов или COM-объектов. Типичный пример — системы распознавания текста (OCR), такие как ABBYY SDK. Инициализация подобного ядра может занимать значительное время (от 30 до 60 секунд), в то время как сама операция обработки файла длится всего несколько секунд. Если каждый из десяти пользователей будет тратить минуту на ожидание при каждом обращении, эффективность работы системы стремится к нулю.

Разберем подробно, почему стандартные механизмы 1С не всегда позволяют решить эту задачу "в лоб", и проанализируем архитектурные подходы, которые помогут инициализировать компоненту один раз и использовать её коллективно.

Почему не работают стандартные средства кэширования?

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

  1. Изоляция сеансов: Кэш с установкой "На время сеанса" является персональным для каждого пользователя. Даже если 10 пользователей работают в одной базе, для каждого из них будет создан свой экземпляр компоненты в памяти сервера. Это не решает задачу коллективного доступа.
  2. Особенности rphost: Внешняя компонента или COMОбъект — это дескриптор в памяти конкретного рабочего процесса rphost. Его нельзя просто так "передать" из одной области памяти в другую.

Также рассмотрим объект ПараметрыПриложения. Это полезный механизм для хранения клиентских настроек, но, как справедливо замечено в обсуждении, он недоступен в серверном контексте и не предназначен для хранения "живых" программных интерфейсов внешних библиотек.

Решение 1: Архитектура «Выделенного воркера» через очередь задач

Этот метод считается классическим для 1С и не требует стороннего ПО. Мы разделяем процесс на "Заказчиков" (пользователей) и "Исполнителя" (служебный сеанс).

Алгоритм реализации:

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

// В служебном сеансе-обработчике
Процедура ИнициализироватьИРаботать()
    Попытка
        Engine = Новый COMОбъект("ABBYY.PassportReaderSdk.RecognitionEngine");
    Исключение
        ЗаписатьЛог("Ошибка инициализации SDK");
        Возврат;
    КонецПопытки;

    Пока Истина Цикл
        Задача = ПолучитьНовуюЗадачуИзРегистра();
        Если Задача = Неопределено Тогда
            Приостановить(5); // Пауза 5 секунд, чтобы не грузить CPU
            Продолжить;
        КонецЕсли;

        // Обработка
        Результат = Engine.Recognize(Задача.Данные);
        СохранитьРезультатВРегистр(Задача.ID, Результат);
    КонецЦикла;
КонецПроцедуры

Преимущества: Компонента инициализирована один раз. Все 10 пользователей лишь добавляют записи в регистр и ждут результата. Память сервера расходуется экономно.

Решение 2: Использование службы компонентов Windows (COM+)

Если ваша компонента является COM-объектом, мы можем заставить саму операционную систему управлять её жизненным циклом. Это позволяет вынести объект за пределы жизненного цикла сессии 1С.

Разберем по шагам настройку в Windows:

  1. Откройте Службы компонентов (dcomcnfg).
  2. Создайте новое приложение COM+.
  3. Добавьте в него вашу DLL (компоненту SDK).
  4. В свойствах созданного приложения на вкладке "Активация" выберите "Приложение сервера".
  5. На вкладке "Библиотека" (или "Свойства") установите флаг "Оставлять процесс в памяти даже при отсутствии обращений" (Leave running when idle).

Теперь, когда первый пользователь вызовет Новый COMОбъект("..."), ОС создаст процесс и инициализирует SDK. Когда пользователь закончит работу, процесс останется "висеть" в памяти. Второй пользователь подключится к уже готовому, прогретому объекту практически мгновенно.

Решение 3: Создание внешнего микросервиса (HTTP-обертка)

Это наиболее современный и масштабируемый подход. Мы выносим работу с тяжелым SDK в отдельное небольшое приложение (например, на языке Python, C# или Go), которое работает как локальный веб-сервер.

Как это работает:

Проанализируем пример вызова из 1С:


Соединение = Новый HTTPСоединение("localhost", 8080);
Запрос = Новый HTTPЗапрос("/recognize");
Запрос.УстановитьТелоИзДвоичныхДанных(ФайлКартинки);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);

Если Ответ.КодСостояния = 200 Тогда
    РезультатТекст = Ответ.ПолучитьТелоКакСтроку();
КонецЕсли;

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

Решение 4: Поддержание сеанса "живым" (Keep-alive)

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

Чтобы объект не умирал, можно настроить регламентное задание, которое раз в 5-10 минут будет обращаться к функции этого модуля под каждым активным пользователем (или использовать одно фоновое задание, если используется механизм разделения данных). Однако, помните, что это лишь "костыль", который не решает проблему инициализации для нового пользователя, который только что зашел в систему.

Резюме и рекомендации

Выбор конкретного метода зависит от ваших технических возможностей:

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

← На главную