Руководство RabbitMQ - Часть 2. Work Queues - рабочие очереди

06.08.26

Интеграция - Внешние источники данных

Перевод руководства и адаптация кода под платформу 1С. https://www.rabbitmq.com/tutorials/tutorial-two-python

Подготовка окружения

Компонента kovalevdmv/1CRabbitMQ, обработка КлиентRMQ. Брокер - как в части 1.

Код примеров собран в расширении RMQ_lessons (malikov-pro/1CRabbitMQ) для запуска через YAxUnit.

Те же сценарии можно вызывать из консоли кода в серверном контексте - например bsl_console и аналоги.

Для имитации работы исполнителя использую ВызватьПаузу() - работает с версии платформы 8.3.25

На чём сосредоточена часть

В части 1 мы отправляли и получали сообщение из именованной очереди. Здесь сделаем рабочую очередь (Work Queue) - она распределяет трудоёмкие задачи между несколькими исполнителями (workers).

Идея простых очередей задач (Task Queues) такая: не делать тяжёлую работу сразу и не ждать окончания выполнения. Задачу планируют к выполнению: упаковывают в сообщение и кладут в очередь. Фоновый исполнитель забирает сообщения и выполняет работу. Если исполнителей несколько - нагрузка делится между ними. Так не приходится «морозить» пользователя, пока идёт долгий расчёт или обработка.

В части 1 слали «Hello World!». Теперь - строки, которые обозначают сложные задачи. Реальной работы (изменение размера картинок, печать PDF) нет: притворимся, что заняты, через ВызватьПаузу. Сложность - число точек в строке (до 10): каждая точка - 0,5 с «работы». Например, Задача 2.......... займёт пять секунд, а Задача 3. - полсекунды.

Исполнителей в 1С можно запускать поднять двумя способами: отдельными клиентами или несколько фоновых заданий в одной ИБ, в примере используются несколько фоновых.

Подключение и канал к брокеру

Два уровня API, которые легко смешать:

  • Подключение (ПодключитьсяКСерверу) - сессия клиента к брокеру (TCP / AMQP): на ней учётные данные и vhost. Параметры - из ОМ_РМКУ_Настройки.СтрокаПодключения().
  • Канал (СоздатьКанал) - логический канал внутри подключения. На нём объявляют очереди, публикуют и потребляют. Настройки вроде предзагрузки (сколько неподтверждённых сообщений держать у получателя) задают на канале, а не на подключении.

Типичный цикл: подключились U94; создали канал U94; работа U94; при необходимости ЗакрытьКанал U94; обязательно ОтключитьсяОтСервера.

Несколько каналов на одном подключении удобны, когда нужны разные настройки (у исполнителя - предзагрузка = 1) или изоляция ошибок канала. Предзагрузку для рабочей очереди разберём после подтверждений.

Отправка задач

Публикуем несколько сообщений (не одно «Hello World!»). Число точек в теле - «вес» задачи (1..10): каждая точка - 0,5 с паузы у исполнителя. Веса задаю массивом, рядом с тяжёлыми кладу несколько лёгких, чтобы в логе было видно - пока один исполнитель тянет задачу на 8-10 точек, второй успевает обработать две-три коротких.

В расширении веса - ОМ_РМКУ_Настройки.ВесаЗадачЧасть2(): 1, 10, 1, 1, 2, 8, 1.

Очередь task_queue и долговечность

Очередь hello из части 1 уже могла быть объявлена с другими параметрами - брокер не даст «тихо» поменять объявление. Для рабочей очереди берём новое имя task_queue: durable + quorum через хелпер из части 1.

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

// Подключение и Канал
ИмяОчереди = ОМ_РМКУ_Настройки.ИмяОчередиЧасть2(); // "task_queue"
Очередь = ОМ_РМКУ_Настройки.ОбъявитьОчередь(КлиентRMQ, Канал, ИмяОчереди);

ВесаЗадач = ОМ_РМКУ_Настройки.ВесаЗадачЧасть2(); // 1, 10, 1, 1, 2, 8, 1
Номер = 0;
Для Каждого Вес Из ВесаЗадач Цикл
	
	Номер = Номер + 1;
	ТекстСообщения = "Задача " + Номер + Лев("..........", Вес);
	СохранитьСообщениеНаДиске = Истина; // persistent
	
	Ответ = КлиентRMQ.ОпубликоватьСообщение(
		Канал, ТекстСообщения, ИмяОчереди, "", Истина, СохранитьСообщениеНаДиске);
	
	Если КлиентRMQ.ЭтоОшибка(Ответ) Тогда
		ВызватьИсключение СтрШаблон("Ошибка отправки: %1", Ответ.Текст);
	КонецЕсли;
	
	// журнал обмена - РС rmq_ОчередьОбменаRMQ 
	ОМ_РМКУ_Настройки.ЗафиксироватьОтправку(ИмяОчереди, ТекстСообщения, "Урок2_Отправитель");
	ОМ_РМКУ_Настройки.СообщитьКонтрольнуюТочку("Отправка в очередь", ТекстСообщения, ИмяОчереди);
	
КонецЦикла;

В расширении это ОМ_ТестRMQ_Lessons.Урок2_Отправитель.

Циклическая диспетчеризация (round-robin)

Одно из преимуществ очереди задач - распараллеливание. Накопился объем сообщений - можно добавить исполнителей для распределения нагрузки.

По умолчанию RabbitMQ отдаёт каждое следующее сообщение следующему получателю по кругу (round-robin): в среднем поровну.

Подтверждение сообщения

Задача у исполнителя может идти несколько секунд. Если брокер считает сообщение обработанным сразу после выдачи, а исполнитель упадёт посередине - задача потеряна. Мы хотим другое: упал исполнитель - задача вернулась в очередь и ушла другому.

В части 1 параметр АвтоматическоеПодтверждение у СоздатьПолучателя (в AMQP это no_ack) часто оставляют Истина: брокер удаляет сообщение сразу после доставки. Для рабочей очереди так недопустимо.

АвтоматическоеПодтверждение = Ложь;

Получатель = КлиентRMQ.СоздатьПолучателя(
	Канал, ИмяОчереди, ТегПолучателя, АвтоматическоеПодтверждение);

// … обработка задачи …

Ответ = КлиентRMQ.ПодтвердитьСообщение(Канал, ДанныеСообщения.Тег);

> Забытое подтверждение. Сообщения, выданные исполнителю, но ещё не подтверждённые копятся увеличивая расход памяти брокера. Проверяйте через Management UI счётчики готовых к выдаче и неподтверждённых. Таймаут подтверждения у брокера по умолчанию ~30 мин - Delivery Acknowledgement Timeout.

Справедливая раздача (предзагрузка)

Round-robin всё ещё может быть несправедливым. Два исполнителя: все нечётные задачи тяжёлые, чётные - лёгкие. Один постоянно занят, второй почти простаивает. Брокер об «весе» не знает и по кругу отдаёт каждое следующее сообщение следующему получателю - вслепую.

Когда подтверждение ручное, можно ограничить предзагрузку: сколько неподтверждённых сообщений брокер держит у одного получателя. В КлиентRMQ это третий параметр СоздатьКанал - КоличествоПредзагруженныхНеПодтвержденныхСообщений.

При значении 1 следующее сообщение не отдадут, пока не подтверждено текущее и свободный исполнитель получит сообщение раньше занятого. При использовании АвтоматическоеПодтверждение = Истина параметр предзагрузки не влияет на распределение.

КоличествоПредзагруженныхНеПодтвержденныхСообщений = 1;
Канал = КлиентRMQ.СоздатьКанал(
	Подключение, Ложь, КоличествоПредзагруженныхНеПодтвержденныхСообщений);

Собираем исполнителя вместе

Полный код - в расширении: ОМ_ТестRMQ_Lessons.Урок2_ИсполнительВФоне. Здесь - скелет того, что собрали выше.

Подключение = КлиентRMQ.ПодключитьсяКСерверу(URI);
КоличествоПредзагруженныхНеПодтвержденныхСообщений = 1;
Канал = КлиентRMQ.СоздатьКанал(
	Подключение, Ложь, КоличествоПредзагруженныхНеПодтвержденныхСообщений);
Очередь = ОМ_РМКУ_Настройки.ОбъявитьОчередь(КлиентRMQ, Канал, ИмяОчереди);

АвтоматическоеПодтверждение = Ложь;
Получатель = КлиентRMQ.СоздатьПолучателя(
	Канал, ИмяОчереди, ТегПолучателя, АвтоматическоеПодтверждение,,,, ТаймаутОжиданияСек);

Пока КлиентRMQ.СледующееСообщение(Получатель) Цикл
	
	ДанныеСообщения = КлиентRMQ.ДанныеСообщения();
	ТекстСообщения = Строка(ДанныеСообщения.Данные);
	
	ЧислоТочек = СтрЧислоВхождений(ТекстСообщения, ".");
	ВызватьПаузу(ЧислоТочек * ПаузаНаТочкуМс); // «работа»
	
	КлиентRMQ.ПодтвердитьСообщение(Канал, ДанныеСообщения.Тег);
	ОМ_РМКУ_Настройки.СообщитьКонтрольнуюТочку(
		"Получение из очереди",
		СтрШаблон("%1 | %2", ПрефиксИсполнителя, ТекстСообщения), // «исполнитель N | Задача …»
		ИмяОчереди);
	
КонецЦикла;

КлиентRMQ.ОтменитьПолучателя(Получатель);
КлиентRMQ.ЗакрытьКанал(Канал);
КлиентRMQ.ОтключитьсяОтСервера(Подключение);

С ручным подтверждением и предзагрузкой = 1 получается рабочая очередь.

Запуск решения

Сначала запускаем исполнителей с прослушиванием очереди после публикуем пакет сообщений, это нужно чтобы фоновые задания исполнителей не закончили работу до запуска отправителя и продемонстрировать разбор "на лету".


 

YAxUnit - тесты набора «Урок 2» Урок2_RoundRobinВОднойИБ

Консоль кода (серверный контекст) - те же сценарии:

// round-robin с паузой (ФЗ + ВызватьПаузу), одной процедурой:
ОМ_ТестRMQ_Lessons.Урок2_RoundRobinВОднойИБ();

// или вручную
Для Номер = 1 По ОМ_РМКУ_Настройки.КоличествоИсполнителейЧасть2() Цикл // по умолчанию 2
	ПараметрыЗадания = Новый Массив;
	ПараметрыЗадания.Добавить(Номер); // U94; метка «исполнитель N» в РС / ЖР
	ПараметрыЗадания.Добавить(0);     // лимит жизни, сек; 0 = из настройки
	ФоновыеЗадания.Выполнить(
		"ОМ_ТестRMQ_Lessons.Урок2_ИсполнительВФоне",
		ПараметрыЗадания);
КонецЦикла;

// когда слушатели уже в очереди - публикуем пакет
ОМ_ТестRMQ_Lessons.Урок2_Отправитель();

Результат работы: В регистре rmq_ОчередьОбменаRMQ - исходящие записи Отправлено и входящие Подтверждено. В ЖР / окне сообщений после round-robin примерно такой лог - у продюсера строка на каждую задачу, у каждого исполнителя - после ack:

05.08.2026 19:16:36 | Старт | очередь: task_queue | данные: Урок2_Отправитель
05.08.2026 19:16:35 | Старт | очередь: task_queue | данные: Урок2_RoundRobinВОднойИБ | исполнителей=2 | задач=7 | лимитФЗ=40 с
05.08.2026 19:16:36 | Отправка в очередь | очередь: task_queue | данные: Задача 1.
05.08.2026 19:16:36 | Отправка в очередь | очередь: task_queue | данные: Задача 2..........
05.08.2026 19:16:36 | Отправка в очередь | очередь: task_queue | данные: Задача 3.
05.08.2026 19:16:36 | Отправка в очередь | очередь: task_queue | данные: Задача 4.
05.08.2026 19:16:36 | Отправка в очередь | очередь: task_queue | данные: Задача 5..
05.08.2026 19:16:36 | Отправка в очередь | очередь: task_queue | данные: Задача 6........
05.08.2026 19:16:36 | Отправка в очередь | очередь: task_queue | данные: Задача 7.
05.08.2026 19:16:36 | Окончание | очередь: task_queue | данные: Урок2_Отправитель
05.08.2026 19:16:36 | Получение из очереди | очередь: task_queue | данные: исполнитель 2 | Задача 1.
05.08.2026 19:16:36 | Старт | очередь: task_queue | данные: исполнитель 1
05.08.2026 19:16:36 | Старт | очередь: task_queue | данные: исполнитель 2
05.08.2026 19:16:37 | Получение из очереди | очередь: task_queue | данные: исполнитель 2 | Задача 3.
05.08.2026 19:16:37 | Получение из очереди | очередь: task_queue | данные: исполнитель 2 | Задача 4.
05.08.2026 19:16:38 | Получение из очереди | очередь: task_queue | данные: исполнитель 2 | Задача 5..
05.08.2026 19:16:41 | Получение из очереди | очередь: task_queue | данные: исполнитель 1 | Задача 2..........
05.08.2026 19:16:41 | Получение из очереди | очередь: task_queue | данные: исполнитель 1 | Задача 7.
05.08.2026 19:16:42 | Окончание | очередь: task_queue | данные: исполнитель 1
05.08.2026 19:16:42 | Получение из очереди | очередь: task_queue | данные: исполнитель 2 | Задача 6........
05.08.2026 19:16:43 | Окончание | очередь: task_queue | данные: исполнитель 2
05.08.2026 19:16:43 | Окончание | очередь: task_queue | данные: Урок2_RoundRobinВОднойИБ | бэклогСнят=0 | приростИсполнителей=7

Пока исполнитель 2 закрывает задачу на 10 точек (W76;5 с), у исполнитель 1 в логе подряд несколько коротких ack - это как раз эффект prefetch=1. Точный порядок строк может чуть съехать изR09;за планировщика ФЗ, важнее расклад по меткам и что лёгкие не ждут окончания «гири».

Таймаут у СоздатьПолучателя (ТаймаутПолучателяСекЧасть2 = 1) - это ожидание пустой очереди, а не «время на обработку». Пока в Ready есть сообщения, СледующееСообщение возвращает их сразу; секунда нужна только чтобы корректно выйти из цикла, когда пакет разобран.

Результат

Настроили рабочую очередь: quorum task_queue, persistent сообщения, ручное подтверждение, несколько фоновых исполнителей, предзагрузка = 1 на канале.

Дальше - часть 3: доставка одного сообщения многим получателям (Publish/Subscribe).

Ссылки на остальные части

Благодарю за внимание.

Создано совместно с Cursor Grok 4.5

Вступайте в нашу телеграмм-группу Инфостарт

RabbitMQ 1С КлиентRMQ Work Queues рабочая очередь prefetch предзагрузка ack подтверждение round-robin фоновое задание durable persistent task queue quorum AMQP интеграция 1CRabbitMQ

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Внешние источники данных Разработчик Аналитик Пользователь 1С:Предприятие 8 1C:Бухгалтерия Узбекистан Беларусь Кыргызстан Молдова Россия Казахстан Платные (руб)

Готовое решение для автоматической выгрузки данных из 1С 8.3 в базу данных ClickHouse, PostgreSQL или Microsoft SQL для работы с данными 1С в BI-системах. «Экстрактор данных 1С в BI» работает со всеми типовыми и нестандартными конфигурациями 1С 8.3 и упрощает работу бизнес-аналитиков. Благодаря этому решению, специалистам не требуется быть программистами, чтобы легко получать данные из 1С в вашей BI-системе.

35000 руб.

15.11.2022    33870    53    49    

51

Внешние источники данных Кадровый учет Файловый обмен (TXT, XML, DBF), FTP Перенос данных 1C Разработчик 1С:Предприятие 8 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

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

85400 руб.

05.10.2022    14600    17    8    

17

Зарплата Внешние источники данных Бюджетный учет Перенос данных 1C Системный администратор Разработчик 1С:Предприятие 8 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

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

122000 руб.

19.08.2020    30669    28    3    

29

Внешние источники данных Зарплата Бюджетный учет Разработчик Бухгалтер 1С:Предприятие 8 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

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

85400 руб.

24.04.2017    57689    99    165    

91

Производство готовой продукции (работ, услуг) Внешние источники данных 1С:Предприятие 8 1С:Управление нашей фирмой 1.6 1С:Управление нашей фирмой 3.0 Лесное и деревообрабатывающее хозяйство Россия Управленческий учет Платные (руб)

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

10370 руб.

24.06.2021    26867    66    55    

48

Файловый обмен (TXT, XML, DBF), FTP Внешние источники данных Бухгалтер Пользователь 1С:Предприятие 8 1С:Бухгалтерия 3.0 Здравоохранение, медицина, стоматология Фармацевтика, аптеки Россия Платные (руб)

Внешняя обработка «Загрузка документов из eФарма» создана для программы 1С:Бухгалтерия предприятия, редакция 3.0 (версии Базовая, Проф и Корп). Обработка позволяет загружать документы в базу 1С из файлов выгрузки, имеющих формат .DBF, которые создаются в программе eФарма или eФарма2, а также из любых других программ, формирующих файлы-выгрузки с таким же расширением.

9760 руб.

15.03.2024    2893    5    0    

7
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. starik-2005 3309 27.09.24 16:07 Сейчас в теме
Статья супер, но повторение - мать учения. Я вот реально потратил кучу кликов, чтобы дойти до сорцов компоненты. Можно было бы сцылку на оное в каждую статью вставлять, а то ищешь, бывает, и находишь самое свежее, а там тридцать кликов до того, как что-то скачать.

ЗЫ: и с каждой следующей статьей этих кликов будет все больше и больше (((
2. malikov_pro 1409 28.09.24 01:13 Сейчас в теме
(1) Принято, соберу обработку после того как приведу код в порядок, сейчас стыдно ...
Чем дальше в код, тем больше костылей. То что просто сделано на python непонятно как сделать на 1С.
3. malikov_pro 1409 02.10.24 07:26 Сейчас в теме
(1) Репо на Github сделал, в статью ссылку добавил, в репо ссылку на компоненту организую.
Возможно сделаю адаптер через REST rabbitmq-management, для тестов и понимания думаю хватит.
4. starik-2005 3309 02.10.24 10:31 Сейчас в теме
(3)
адаптер через REST rabbitmq-management
Вчера читал про 27-й релиз и веб-сокет в нем. 1С как раз позиционируют это для телефонии, очередей и брокеров. Я так понял, что кролик в базовом своем сценарии через веб-сокет и работает. Так что, предположу, скоро эти все штуки будут без надобности )))
5. malikov_pro 1409 03.10.24 07:27 Сейчас в теме
(4) Благодарю за идею с ws. Но он используется через плагины:
RabbitMQ поставляется с двумя плагинами, которые могут позволить вам взаимодействовать с RabbitMQ из браузера: плагинами Web-STOMP и Web-MQTT.
Источник https://www.cloudamqp.com/blog/rabbitmq-and-websockets-part-2-web-mqtt-web-stomp-and-web-amqp.html, пред статья про форматы, полезная, думаю переведу.

Для пробы и понимания думаю лучше REST, для продакшена можно и ws, добро пожаловать в адаптеры.

27 версии платформы не обязательно ждать https://infostart.ru/1c/tools/937068/
6. starik-2005 3309 03.10.24 10:25 Сейчас в теме
(5)
27 версии платформы не обязательно ждать
Ага, 26-й - тоже )))
https://infostart.ru/1c/articles/2044928/
Для отправки сообщения требуется регистрация/авторизация