RabbitMQ-порядок доставки сообщений
Мне нужно выбрать нового брокера очередей для моего нового проекта.
на этот раз мне нужна масштабируемая очередь, поддерживающая pub/sub, и сохранение порядка сообщений является обязательным.
читаю Комментарий Алексея: он пишет:
"действительно, мы думаем, что RabbitMQ обеспечивает более сильный порядок, чем Кафка"
Я прочитал раздел заказа сообщений в документах rabbitmq:
"сообщения могут быть возвращены в очередь с помощью методов AMQP та характеристика в повторной постановки параметр (базовый.выздоравливай, Бейсик.отклонить и основной.НЭК), или из-за канала закрытие при удержании неподтвержденных сообщений...С версии 2.7.0 и выше индивидуальные потребители по-прежнему могут наблюдать сообщения из заказать, если очередь имеет несколько подписчиков. Это связано с действиями другие подписчики, которые могут запрашивать сообщения. С точки зрения очереди сообщения всегда хранятся в публикации порядок."
Если мне нужно обрабатывать сообщения по их заказу, я могу использовать только rabbitMQ с эксклюзивной очередью для каждого потребителя?
считается ли RabbitMQ хорошим решением для упорядоченной очереди сообщений?
4 ответов
Ну, давайте более подробно рассмотрим сценарий, который вы описываете выше. Я думаю, что важно вставить документация непосредственно перед фрагментом в вашем вопросе, чтобы предоставить контекст:
раздел 4.7 спецификации ядра AMQP 0-9-1 объясняет условия, при которых гарантируется заказ: сообщения, опубликованные в один канал, проходящий через один обмен и одну очередь и один исходящий канал будет получен в том же прикажите, чтобы они были отправленный. RabbitMQ предлагает более сильные гарантии с момента выпуска 2.7.0.
сообщения могут быть возвращены в очередь с помощью методов AMQP, которые имеют параметр requeue (basic.выздоравливай, Бейсик.отклонить и основной.НЭК), или из-за закрытия канала при хранении неподтвержденных сообщений. Любой из в этих сценариях сообщения должны быть запрошены в задней части очередь для выпусков RabbitMQ ранее 2.7.0. От выхода в RabbitMQ 2.7.0, сообщения всегда проходят в очередь в порядке публикации,даже при наличии requeueing или закрытия канала. (курсив)
таким образом, ясно, что RabbitMQ, начиная с 2.7.0, делает довольно резкое улучшение по сравнению с оригинальной спецификацией AMQP в отношении порядка сообщений.
с множественными (параллельными) потребителями, заказ обработки нельзя гарантировать.
Третий абзац (вставленный в вопрос) продолжает давать отказ, который я перефразирую: "если у вас есть несколько процессоров в очереди, нет гарантии, что сообщения будут обрабатываться в порядке.- Все, что они говорят, это то, что кролик не может бросить вызов законам математики.
рассмотрим линию клиентов в банке. Этот конкретный банк гордится тем, что помогает клиентам в порядке, в котором они пришли в банк. Клиенты выстраиваются в очередь и обслуживаются следующими из 3 доступных кассиров.
этот утром так получилось, что все три кассира стали доступны одновременно, и к ним подошли следующие 3 клиента. Внезапно первый из трех кассиров заболел и не смог закончить обслуживание первого клиента в очереди. К тому времени, как это произошло, кассир 2 закончил с клиентом 2, а кассир 3 уже начал обслуживать клиента 3.
теперь может произойти одно из двух. (1) первый клиент в линии может пойти назад к голове линии или (2) первое клиент может опередить третьего клиента, заставив кассира перестать работать с третьим клиентом и начать работать с первым. Этот тип упреждающей логики не поддерживается RabbitMQ и любым другим брокером сообщений, о котором я знаю. В любом случае, первый клиент в конечном итоге не получает помощь первым - это делает второй клиент, которому повезло получить хорошего, быстрого кассира с места в карьер. Единственный способ гарантировать клиентам помощь - это помощь одного кассира клиенты по одному, что вызовет серьезные проблемы с обслуживанием клиентов для банка.
Я надеюсь, что это поможет проиллюстрировать проблему, о которой вы спрашиваете. Невозможно гарантировать, что сообщения обрабатываются в порядке в каждом возможном случае, учитывая, что у вас есть несколько потребителей. Не имеет значения, есть ли у вас несколько очередей, несколько эксклюзивных потребителей, разные брокеры и т. д. - нет никакой возможности гарантировать априори что сообщения отвечают в порядке с несколько потребителей. Но RabbitMQ приложит все усилия.
порядок сообщений сохраняется в Кафке, но только внутри разделов, а не глобально. Если ваши данные нуждаются в глобальном упорядочении и разделах, это затрудняет работу. Однако, если вам просто нужно убедиться, что все те же события для одного и того же пользователя и т. д... в конечном итоге в том же разделе, чтобы они были правильно упорядочены, вы можете это сделать. Производитель отвечает за раздел, в который они пишут, поэтому, если вы можете логически разделить свои данные, это может быть предпочтительный.
Я думаю, что в этом вопросе есть две вещи, которые не похожи, порядок потребления и порядок обработки.
очереди сообщений могут-в определенной степени - дать вам гарантию того, что сообщения будут потребляться в порядке, однако они не могут дать вам никаких гарантий относительно порядка их обработки.
основное различие здесь в том, что есть некоторые аспекты обработки сообщений, которые не могут быть определены во время потребления, для пример:
Как уже упоминалось, потребитель может потерпеть неудачу при обработке, здесь порядок потребления сообщения был правильным, однако потребитель не смог обработать его правильно, что заставит его вернуться в очередь, и до сих пор порядок потребления все еще не поврежден, но мы не знаем, как порядок обработки теперь
Если под "обработкой" мы подразумеваем, что сообщение Теперь отброшено и полностью завершено, то рассмотрим случай, когда ваше время обработки не линейно, другими словами, обработка одного сообщения занимает больше времени, чем другое, поэтому, если сообщение 3 занимает больше времени, чем ожидалось, то сообщения 4 и 5 могут быть израсходованы и завершить обработку до сообщения 3
поэтому, даже если вам удалось вернуть сообщение в начало очереди (что, кстати, нарушает порядок потребления), вы все равно не можете гарантировать, что все сообщения до следующего сообщения закончены обработка.
Если вы хотите обеспечить порядок обработки тут:
- есть только 1 потребительский экземпляр во все времена
- или не используйте очередь обмена сообщениями и выполняйте обработку синхронным методом блокировки, что может показаться плохим, но во многих случаях и бизнес-требования полностью действительны, а иногда даже критичны
существуют надлежащие способы гарантировать порядок сообщений в подписках RabbitMQ.
если вы используете несколько потребителей, они будут обрабатывать сообщение с помощью общего ExecutorService
. См. также ConnectionFactory.setSharedExecutor(...)
. Вы можете установить Executors.newSingleThreadExecutor()
.
если вы используете Consumer
С одной очередью вы можете связать эту очередь, используя несколько bindingKeys (у них могут быть подстановочные знаки). Сообщения будут помещены в очередь в том же порядке, в котором они были получены брокер сообщений.
например у вас есть один издатель, который публикует сообщения, где порядок важен:
try (Connection connection2 = factory.newConnection();
Channel channel2 = connection.createChannel()) {
// publish messages alternating to two different topics
for (int i = 0; i < messageCount; i++) {
final String routingKey = i % 2 == 0 ? routingEven : routingOdd;
channel2.basicPublish(exchange, routingKey, null, ("Hello" + i).getBytes(UTF_8));
}
}
теперь вы можете получать сообщения от обоих темы на очереди в том же порядке, в котором они были опубликованы:
// declare a queue for the consumer
final String queueName = channel.queueDeclare().getQueue();
// we bind to queue with the two different routingKeys
final String routingEven = "even";
final String routingOdd = "odd";
channel.queueBind(queueName, exchange, routingEven);
channel.queueBind(queueName, exchange, routingOdd);
channel.basicConsume(queueName, true, new DefaultConsumer(channel) { ... });
на Consumer
теперь будут получать сообщения в порядке, в котором они были опубликованы, независимо от того, что вы использовали различные темы.
в документации RabbitMQ есть несколько хороших 5-минутных учебников, которые могут быть полезны: https://www.rabbitmq.com/tutorials/tutorial-five-java.html