Параметр Таймаут в методе ПолучитьСообщение компоненты


#1

Вызов метода ПолучитьСообщение в случае пустой очереди сообщений блокирует поток до тех пор, пока не будет достигнут таймаут, несмотря на то, что сервер RabbitMQ отвечает на порядок быстрее. Т.е. если сообщение есть, метод отрабатывает быстро, а если сообщений нет - ждем истечения таймаута. Подобное поведение выглядит странным, т.к. таймаут должен предполагать допуски по времени на недоступность/загруженность сервера/сети, и не использоваться, если сервер RabbitMQ доступен и просто очередь пустая. В случае большого количества обрабатываемых очередей мы теряем много времени просто на ожидание истечения таймаута.
Прошу прокомментировать такое поведение и исправить обработку параметра Таймаут.

Пример кода:

Таймаут = 1000;
СообщениеПрочитано = Клиент.BasicConsumeMessage(ИмяПотребителя, Результат, Таймаут);


#2

Первое - пожалуйста подсматривайте в подсистему. А не пишите методы работы с компонентой напрямую с нуля.

  • ОбщийМодуль.ОчередьСообщений
// Создает объект, читающий события из заданной очереди
//
// Параметры:
//  ИмяОчереди	   - Строка. Имя очереди
//
//  КлючСоединения - произвольное имя, по которому конфигурация-потребитель
//                   сможет выбрать нужный сервер очередей
// 
// Возвращаемое значение:
//   Класс ПолучательСобытий
//
Функция НовыйПодписчик(Знач ИмяОчереди, Знач КлючСоединения = "") Экспорт

	Потребитель = Обработки.ПолучательСобытий.Создать();
	Потребитель.ПодписатьсяНаОчередь(ИмяОчереди, КлючСоединения);
	Возврат Потребитель;

КонецФункции // НовыйПодписчик()

Обработки.ПолучательСобытий

// Получить сообщение
// Считывает сообщение из очереди. Метод блокирует текущий поток выполнения, пока не будет получено сообщение или не достигнут таймаут.
//
// Параметры:
//  ИмяПотребителя	 - Строка	 - имя зарегистрированного потребителя
//  Результат		 - Строка	 - выходной параметр. Тело сообщения.
//  Таймаут			 - Число	 - таймаут ожидания сообщения в миллисекундах. -1 означает неограниченное ожидание
// 
// Возвращаемое значение:
//   - Булево. Истина, если сообщение получено, Ложь если достигнут таймаут.
//
Функция ПолучитьСообщение(Знач ИмяПотребителя, Результат, Знач Таймаут = -1) Экспорт

	// обнуление результата
	Результат = Неопределено;
	Попытка
		Возврат Клиент.BasicConsumeMessage(ИмяПотребителя, Результат, Таймаут);
	Исключение
		СгенерироватьТочнуюОшибку(ИнформацияОбОшибке());
	КонецПопытки;

КонецФункции // ПолучитьСообщение()

То есть описанное вами поведение штатное


#3

Второе - я так понимаю вы хотите новый метод

ПолучитьСообщениеБезОжидания()

понимаете тут такое дело, что требуется вспомнить параметры протокола amqp

У подписчика есть жизненный цикл - он же подписчик, ожидающий сообщения из очереди. ОЖИДАЮЩИЙ в потоке исполнения когда сервер ему доставит сообщение, если и когда оно появится.

Из документации

This method asks the server to start a “consumer”, which is a transient request for messages from a specific queue. Consumers last as long as the channel they were declared on, or until the client cancels them.

То есть как долго будет клиент ждать сообщение в канале доставки - это сугубо его личное дело. Именно за это личное дело отвечает параметр таймаут.

  • -1 будем ждать пока не появится
  • 0 - вообще не ждем
  • 1000 - ждем секунду

#4

Ну и почти последнее - почему не используется штатный модуль

//////////////////////////////////////////////////////////////////////
// ПРОГРАММНЫЙ ИНТЕРФЕЙС

// Процедура позволяет конфигурации-потребителю событий зарегистрировать
// свои процедуры обработки сообщений в разрезе имен очередей
//
// Параметры:
//   Обработчики - Соответствие - коллекция зарегистрированных обработчиков событий
//
Процедура ПриРегистрацииОбработчиковСообщений(Знач Обработчики) Экспорт

	// Для регистрации обработчика необходимо использовать следующий код:
	//
	// 		ПолучениеСообщенийСлужебный.ДобавитьОбработчикСообщения(Обработчики, "МойОбщийМодуль.МойМетодОбработки", 2);
	// 		ПолучениеСообщенийСлужебный.ДобавитьОбработчикСообщения(Обработчики, "МойОбщийМодуль.МойМетодОбработки");


#5

За большое количество обрабатываемых очередей ответственен ОбщийМодуль. ПолучениеСообщенийПереопределяемый

Который в свою очередь обеспечивает наполнение Справочника.ПодпискиНаОчередиСообщений


#6

Правильно ли я понимаю, что если нам не нужно ждать сообщения в очереди, а просто получить его, если оно есть, и пойти дальше, если его нет - то мы можем установить Таймаут = 0? Будет ли получение получение сообщений работать стабильно?


#7

Да, Таймаут = 0 не будет ожидать.

Но все зависит от того, что вам требуется.

если у вас задание опроса стартует все равно по таймеру, вы фактически сдвигаете проблему ожидания на период запуска следующего задания.