Как передавать данные между фоновыми заданиями в 1С в оперативной памяти?

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

При разработке высоконагруженных многопоточных систем на платформе 1С:Предприятие программисты часто сталкиваются с необходимостью организовать быстрый межпроцессный обмен (Inter-Process Communication, IPC). Типичный сценарий: несколько параллельных фоновых заданий выполняют тяжелые расчеты или обработку данных и должны отправлять логи, метрики или промежуточные статусы в основной поток в режиме реального времени.

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

Почему стандартные методы не подходят для работы в ОЗУ?

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

  1. Хранилище общих настроек (и другие хранилища настроек): Данные этих хранилищ физически записываются в таблицы СУБД. При высокой частоте обращений (десятки раз в секунду) база данных начинает тратить ресурсы на запись транзакционного лога, накладывать блокировки на таблицы настроек, что сводит на нет всю пользу от многопоточности.
  2. Временное хранилище (ПоместитьВоВременноеХранилище): Многие разработчики ошибочно полагают, что временное хранилище работает исключительно в оперативной памяти. Согласно официальной документации фирмы «1С», данные временного хранилища (сеансовые данные) принудительно сбрасываются на диск сервера приложений в каталог сеансовых данных. Кроме того, данные, помещенные в хранилище внутри фонового задания, становятся доступны основному сеансу только после полного завершения работы этого фонового задания, что делает невозможным мониторинг в реальном времени.

Разберем работающие альтернативные архитектурные решения.

Решение 1. Использование механизма сообщений пользователя (Самый быстрый нативный способ)

Наиболее эффективным встроенным инструментом для передачи данных «снизу вверх» (от фонового задания к запустившему его сеансу) является использование объекта СообщениеПользователю в связке с методом ПолучитьСообщенияПользователю.

Данные, передаваемые через этот механизм, буферизуются непосредственно в оперативной памяти рабочего процесса rphost (или менеджера кластера rmngr) и никогда не записываются на жесткий диск. Чтобы передавать сложные структуры данных, массивы или таблицы, мы применим сериализацию в формат JSON.

Рассмотрим по шагам реализацию этого паттерна.

Шаг 1. Код внутри фонового задания (отправитель данных)

Внутри выполняемого фонового задания мы упаковываем наши порции логов или результатов в структуру, сериализуем их в JSON-строку и отправляем с помощью метода Сообщить:


// Процедура фонового задания
Процедура ВыполнитьПараллельнуюОбработку(ПараметрыЗадачи) Экспорт
    
    // Имитируем цикл обработки данных
    Для Счетчик = 1 По 100 Цикл
        
        // Формируем структуру с данными для отправки
        СтруктураЛога = Новый Структура;
        СтруктураЛога.Вставить("ИдентификаторПотока", ПараметрыЗадачи.Идентификатор);
        СтруктураЛога.Вставить("ТекущийШаг", Счетчик);
        СтруктураЛога.Вставить("Время", ТекущаяДатаСеанса());
        СтруктураЛога.Вставить("Статус", "Успешно обработано");
        
        // Сериализуем структуру в JSON
        ЗаписьJSON = Новый ЗаписьJSON;
        ЗаписьJSON.УстановитьСтроку();
        ЗаписатьJSON(ЗаписьJSON, СтруктураЛога);
        СтрокаДанных = ЗаписьJSON.Закрыть();
        
        // Отправляем сериализованные данные "наверх" в память процесса rphost
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = СтрокаДанных;
        Сообщение.Сообщить();
        
        // Имитация задержки работы
        ФизическаяПауза(0.1); 
    КонецЦикла;
    
КонецПроцедуры

Шаг 2. Код в основном потоке (получатель данных)

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


// Запуск и опрос фонового задания в основном потоке
Процедура МониторингВыполненияФоновыхЗаданий()
    
    ПараметрыЗадачи = Новый Структура("Идентификатор", "Поток_1");
    ФоновоеЗадание = ФоновыеЗадания.Выполнить("МодульФоновыхЗадач.ВыполнитьПараллельнуюОбработку", ПараметрыЗадачи);
    
    Пока Истина Цикл
        
        // Получаем свойства для контроля состояния
        СвойстваФЗ = ФоновоеЗадание.ПолучитьСвойства();
        СостояниеФЗ = СвойстваФЗ.Состояние;
        
        // Читаем новые сообщения из оперативной памяти сервера
        // Параметр "Истина" очищает полученные сообщения из буфера rphost
        МассивСообщений = ФоновоеЗадание.ПолучитьСообщенияПользователю(Истина);
        
        Для Каждого Сообщение Из МассивСообщений Цикл
            СтрокаJSON = Сообщение.Текст;
            
            // Пытаемся десериализовать JSON
            Попытка
                ЧтениеJSON = Новый ЧтениеJSON;
                ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
                ДанныеЛога = ПрочитатьJSON(ЧтениеJSON);
                
                // Здесь мы можем мгновенно перенаправить данные во внешний сервис логирования
                ОтправитьЛогВоВнешнююСистему(ДанныеЛога.ИдентификаторПотока, ДанныеЛога.ТекущийШаг, ДанныеЛога.Время);
            Исключение
                // Если пришло обычное системное сообщение (не JSON)
                ЗаписатьВЖурналРегистрации("Внимание! Получено неформатированное сообщение: " + СтрокаJSON);
            КонецПопытки;
        КонецЦикла;
        
        Если СостояниеФЗ <> СостояниеФоновогоЗадания.Активно Тогда
            Прервать;
        КонецЕсли;
        
        // Делаем небольшую паузу между опросами
        ПриостановитьПоток(0.5); 
    КонецЦикла;
    
КонецПроцедуры

Решение 2. Использование RAMDrive (виртуального диска в ОЗУ)

Если вам требуется организовать обмен не только в направлении «снизу вверх», но и «по горизонтали» (между параллельными фоновыми заданиями), либо объемы передаваемых данных слишком велики для сериализации в JSON внутри сообщений, можно использовать технологию **RAMDrive**.

Для этого на сервере приложений 1С разворачивается специализированное ПО (например, бесплатный ImDisk Toolkit), которое выделяет часть оперативной памяти сервера ОС и монтирует ее в систему как обычный локальный диск (например, диск R:\).

Рассмотрим особенности работы с RAMDrive из 1С:

Пример записи данных фоновым заданием на RAMDrive:


ИмяФайлаЛога = "R:\logs\thread_1_" + Формат(ТекущаяДата(), "ДФ=ггггММддЧЧммсс") + ".txt";
ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаЛога, КодировкаТекста.UTF8);
ЗаписьТекста.ЗаписатьСтроку(СтрокаJSONДанных);
ЗаписьТекста.Закрыть();

Решение 3. Использование In-Memory хранилищ (Redis)

Для наиболее сложных архитектурных задач, требующих гарантированной доставки, высокой скорости работы, поддержки очередей сообщений и возможности обмена данными между любыми процессами, рекомендуется использовать внешние **In-Memory Key-Value хранилища**, такие как **Redis**.

Redis разворачивается непосредственно на сервере приложений или в локальной сети. Общение фоновых заданий 1С с СУБД Redis можно реализовать следующими способами:

Использование внешнего in-memory хранилища полностью разгружает рабочий процесс 1С rphost и исключает раздувание его адресного пространства при обработке гигантских массивов логирования.

Решение 4. Нативные HTTP-сервисы 1С и Асинхронные обработчики

Если требуется передавать информацию в реальном времени, можно развернуть внутренний легковесный HTTP-сервис внутри самой базы 1С. Каждое фоновое задание отправляет порции данных с помощью асинхронных HTTP-запросов на этот сервис.

Поскольку HTTP-сервисы обрабатываются пулом быстрых потоков в оперативной памяти rphost, при правильной настройке (без записи данных в СУБД в процессе обработки запроса) этот метод позволяет организовать быстрый и надежный транспорт данных, который можно масштабировать на несколько серверов в кластере.

Сравнительный анализ методов передачи данных в ОЗУ

Проанализируем характеристики каждого метода, чтобы выбрать оптимальный инструмент под ваши задачи:

  1. Метод Сообщить + JSON:
    • Сложность реализации: Низкая (только штатный код 1С).
    • Скорость обмена: Очень высокая.
    • Где хранятся данные: ОЗУ процесса rphost.
    • Ограничения: Только однонаправленный обмен «фоновое задание -> родительский сеанс».
  2. Виртуальный диск RAMDrive:
    • Сложность реализации: Средняя (требуется настройка ПО на сервере ОС).
    • Скорость обмена: Высокая (ограничена скоростью файловой подсистемы ОС).
    • Где хранятся данные: ОЗУ сервера под управлением ОС.
    • Ограничения: Требуется администрирование операционной системы, сложно масштабировать в многосерверных кластерах 1С.
  3. In-Memory базы данных (Redis):
    • Сложность реализации: Высокая (требуется установка Redis и использование ВК или HTTP-запросов).
    • Скорость обмена: Максимально возможная.
    • Где хранятся данные: ОЗУ выделенного сервера Redis.
    • Ограничения: Требуется развертывание дополнительной инфраструктуры.

Выяснив причины медленной работы СУБД при логировании и применив любой из предложенных вариантов переноса данных в оперативную память, вы сможете поднять производительность ваших многопоточных процедур в разы, полностью ликвидировав задержки на дисковые операции ввода-вывода.

← На главную