Как гарантировать порядок сообщений в RabbitMQ (или любой другой службе асинхронной очереди сообщений) - PullRequest
0 голосов
/ 22 ноября 2018

У меня есть приложение Java, которое публикует события в RabbitMQ.У него есть одна очень важная характеристика: порядок сообщений должен сохраняться всегда.Потребитель может обрабатывать дубликаты, но не может обрабатывать, когда сообщение 2 ставится в очередь перед сообщением 1, так сказать.

В последнее время я много читал о RabbitMQ, и я чувствую, что есть только решениеДля этого: установите канал в режиме confirm (https://www.rabbitmq.com/confirms.html - по сути, это заставляет брокера подтвердить публикацию) и публиковать по одному.Один за другим я имею в виду, что сообщение 2 публикуется только после того, как RabbitMQ подтвердил (посредством асинхронного ACK ответа), что сообщение 1 действительно хорошо получено и сохраняется.

Я пытался это сделать вконцептуальная реализация, и хотя это работает нормально, это очень медленно, без преувеличения.Что имеет смысл: в конце концов, мы теперь ограничиваем нашу скорость передачи сообщений до 1 сообщения за раз.

Так что это подводит меня к моему вопросу: существуют ли другие, более производительные способы обеспечения того, чтобы порядок сообщений всегда былсохранено (либо в RabbitMQ, либо с помощью других подходов)?

Хотя меня беспокоит RabbitMQ, я считаю, что этот вопрос может быть применен к любому виду асинхронной службы очереди сообщений.

1 Ответ

0 голосов
/ 22 ноября 2018

Клиенты RabbitMQ ставят в очередь в том же порядке, что вы отправили .Когда подписчики отключаются, вы получаете сетевые сплиты или сообщения NACKs подписчика, которые они могут переупорядочивать;и даже тогда RMQ пытается удерживать их в том же приблизительном порядке, повторно ставя в очередь в той же позиции или как можно ближе к той же позиции.

Вы можете сделать это так, как вы предлагаете; принимать по одному сообщению за раз , потому что, если вы принимаете сообщение, но вылетаете до того, как получите его от брокера, оно появится, когда ваш сервис вернется в ту же позицию.

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

Другим решением будет обеспечение упорядочения обработки в службе приема путем «повторного упорядочения»«сообщения основаны на их логических временных / последовательных номерах.

Я написал гораздо более подробное руководство в виде аннотированного кода здесь https://github.com/haf/rmq-publisher-confirms-hopac/blob/master/src/Server/Shared/RabbitMQ.fs - с помощью пакетной обработки вы можете выполнить повторную последовательность.Кроме того, если ваша идемпотентность встраивает последовательные порядковые номера в свою логику, вы можете начать принимать партии, и каждое событие будет идемпотентным, несмотря на то, что его повторно потребляют.

...