Проблема стабильности обмена данными через RabbitMQ с использованием внешней компоненты BITERP.PinkRabbitMQ является довольно распространенной в сообществе 1С-разработчиков. Зачастую пользователи сталкиваются с тем, что фоновые задания «мертво» зависают, потребляют 100% ресурсов процессора или приводят к аварийному завершению рабочих процессов сервера rphost. В этой статье мы подробно разберем причины такого поведения и рассмотрим проверенные стратегии решения проблемы.
Прежде чем переходить к решениям, проанализируем ситуацию. Компонента BITERP.PinkRabbitMQ написана на C++ с использованием Native API. Основная сложность заключается в корректном управлении ресурсами внутри этой компоненты. Выясним основные технические причины сбоев:
Connect более одного-двух раз в рамках одного сеанса приводит к порче памяти. Даже если вы устанавливаете переменную Клиент = Неопределено, внутренние дескрипторы в C++ не всегда освобождаются корректно.cannot parse integer from empty string, связанная с некорректной передачей или хранением параметра Offset (смещение) в настройках БИТ.МДТ.Попытка...Исключение, а просто прекращает выполнение кода.Для сценариев, когда объем сообщений невелик (например, десятки или сотни сообщений в день для синхронизации справочников), самым надежным способом будет полный отказ от использования внешних компонент в пользу встроенного в 1С механизма HTTPСоединение. Рассмотрим подробнее этот подход.
RabbitMQ предоставляет мощный REST API (через плагин rabbitmq_management), который позволяет отправлять и получать сообщения. Рассмотрим пример получения сообщения через HTTP-запрос:
// Пример получения сообщения через REST API
Соединение = Новый HTTPСоединение(СерверРэбит, ПортРэбит, Логин, Пароль);
Заголовок = Новый Соответствие;
Заголовок.Вставить("Content-Type", "application/json");
// Подготавливаем параметры запроса (сколько сообщений забрать, нужно ли подтверждение)
ТелоЗапроса = "{""count"":1,""requeue"":false,""encoding"":""auto"",""ackmode"":""ack_requeue_false""}";
Запрос = Новый HTTPЗапрос("/api/queues/" + ВиртуальныйХост + "/" + ИмяОчереди + "/get", Заголовок);
Запрос.УстановитьТелоИзСтроки(ТелоЗапроса);
Ответ = Соединение.ОтправитьДляОбъекта(Запрос);
Если Ответ.КодСостояния = 200 Тогда
// Разбираем JSON ответа и извлекаем Payload
КонецЕсли;
Преимущества REST API:
rphost.Минус: Скорость работы через HTTP ниже, чем по протоколу AMQP, однако для периодической синхронизации справочников это не критично.
Если отказаться от компоненты PinkRabbitMQ невозможно (например, из-за жесткой привязки в конфигурации БИТ), проанализируем архитектурный обходной путь. Поскольку компонента «течет» и зависает при длительной работе, мы должны ограничить время её жизни.
Разберем алгоритм безопасной работы по шагам:
// Пример безопасного цикла обработки
Процедура ВыполнитьОбмен() Экспорт
НачалоРаботы = ТекущаяДата();
МаксВремяРаботы = 120; // 2 минуты
Попытка
ПодключитьВнешнююКомпоненту("BITERP.PinkRabbitMQ");
Рэбит = Новый("AddIn.PinkRabbitMQ.PinkRabbitMQ");
Если НЕ Рэбит.Connect(ПараметрыПодключения) Тогда
Возврат;
КонецЕсли;
Пока ТекущаяДата() - НачалоРаботы < МаксВремяРаботы Цикл
Сообщение = Рэбит.BasicConsumeMessage(ИмяОчереди);
Если Сообщение = Неопределено Тогда
Прервать;
КонецЕсли;
ОбработатьСообщение(Сообщение);
КонецЦикла;
Исключение
ЗаписатьЛогОшибки(ОписаниеОшибки());
КонецПопытки;
// Явное удаление объекта для Native API
Рэбит = Неопределено;
КонецПроцедуры
Если вам требуется высокая производительность протокола AMQP, но текущая компонента работает нестабильно, рассмотрим альтернативы:
COM-объект или обертку .NET. Это исключает проблемы с Native API 1С, так как управление памятью берет на себя среда CLR.Проанализируем настройки самого сервера RabbitMQ, которые могут помочь в борьбе с зависаниями. Выясним, установлен ли у вас Heartbeat. Это критически важный параметр. Рекомендуется устанавливать его в значение около 60 секунд. Это позволит компоненте быстрее понять, что соединение с сервером разорвано, и выдать ошибку в 1С, вместо того чтобы бесконечно ждать ответа от сокета.
Также проверьте системную ошибку 10060 (Connection timed out). Если она возникает часто, это может указывать на агрессивные настройки файрвола, который обрывает «тихие» TCP-сессии. В этом случае использование Heartbeat становится обязательным.
Подведем итог. Если ваша система обменивается небольшим количеством данных, выбирайте REST API — это сэкономит вам десятки часов на отладку «мистических» зависаний сервера. Если же нагрузка высока, переходите на стратегию краткоживущих фоновых заданий или используйте альтернативные внешние компоненты, так как текущая реализация PinkRabbitMQ имеет фундаментальные проблемы с управлением памятью в среде 1С.