2011-06-14 4 views
3

У нас есть прочная очередь RabbitMQ. Когда потребитель получает элемент из очереди, он обрабатывает его, а затем подтверждает его. Если потребитель не обрабатывает элемент, он печатает ошибку, ожидая, что кто-то исправит проблему и остановится. Никакое подтверждение не отправляется. Когда потребитель перезапускает элемент, который он получает, это следующий элемент в очереди, а не элемент без знака. Basic.Recover() не помогает (с использованием клиента .NET). Любые идеи о том, как заставить его работать как очередь - всегда получайте первый элемент, если он не отключен.RabbitMQ Basic Recover не работает

ответ

3

См. this entry in the RabbitMQ FAQ. Хотя вы можете захотеть, чтобы RabbitMQ снова запустил ваши незакрепленные сообщения прямо в голову очереди (где они были до того, как ваш потребитель потянул их), реальность, вероятно, будет отличаться, как вы уже испытали.

Так что это не то, что Basic.Recover() не работает (сообщение был помещен обратно в очередь для будущей переработки) только, что он не работает так, как вы ожидали.

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

+0

мой план состоит в том, чтобы установить счетчик предварительной выборки до 1, сериализовать сообщение об ошибке в файл и все равно. Когда процесс запустится, он получит первое сообщение из этого файла, обработает его, а затем возобновит потребление очереди. – Kimi

+1

Это не работает, если процесс был убит. В любом случае, Кролик поставит его в конце очереди. – Kimi

2

Сообщение может потребляться два способами Noack = ложный или истинный Noack =

Noack является параметром на обоих Model.BasicConsume и Model.BasicGet

Когда Noack установлен в истинные сообщения автоматически удаляется из очередь после доставки. Если noAsk установлено в false, сообщения удаляются только при вызове basicAck.

Если noAck = false, и вы не вызываете basicAck, сообщение останется, но вы не получите других пользователей до тех пор, пока вы не перезапустите приложение (или не закройте соединение, которое его потребляло в первую очередь). Если вы вызываете BasicReject, сообщение будет повторно отправлено подписчику.

Надеюсь, это поможет.

+0

Вы, вероятно, должны изменить свои многочисленные «noAsk» примеры выше на «noAck». –

0

Вы можете получить это поведение, имея пару очередей, один высокий приоритет и один нормальный приоритет. Установите счетчик предварительной выборки равным 1, а затем чередуйте очереди между ними, используя basic.get. В большинстве случаев очередь приоритетов будет пустой, но когда вы захотите запросить, опубликуйте сообщение снова в очереди с высоким приоритетом.

Это работает в сценарии, когда у вас есть несколько процессов, потребляющих поток сообщений, и один процесс решает ответить на сообщение. Это сообщение будет получено почти сразу другим процессом.

+0

мой сценарий очень прост - есть один потребитель, порядок сообщений критический, а в случае неожиданного отключения (сбой питания) RabbitMQ помещает первое сообщение очереди в конец очереди. Поэтому я предполагаю, что я должен использовать другого брокера, чтобы сначала сохранить первое сообщение, пока клиент не вычеркнет его. – Kimi

+0

Я задал более важный вопрос здесь http://stackoverflow.com/questions/6369190/what-open-source-message-queuing-software-provides-durability-with-strict-orderin – Kimi

1

RabbitMQ, похоже, зафиксировал часть этой проблемы since 2.7.0, так как теперь сообщения будут отправлены в порядке публикации. Хотя, если у вас более одного подписчика на очередь, у вас может быть сообщение, поступившее из первоначального заказа.