Как я могу гарантировать, что только один потребитель фактически использует опубликованное сообщение? - PullRequest
0 голосов
/ 09 декабря 2018

Я использую Rabbitmq с микросервисной архитектурой.Я использую тему и прямой обмен для многих из моих сценариев использования, и это прекрасно работает.Однако у меня есть сценарий использования, когда мне нужно удалить запись из базы данных.Когда я удалил запись, необходимо вызвать несколько других служб и сохранить / удалить записи, на которые есть ссылки.Я мог бы добиться этого, просто позвонив в те службы с прямым обменом, но я читал, что это предпочтение хореографии, а не оркестровка.Это означает, что я должен реализовать шаблон публикации / подписки (fanout в rabbitmq).Мой вопрос заключается в том, что если я использую шаблон публикации / подписки в распределенной системе, как убедиться, что только один экземпляр службы потребляет опубликованные сообщения?

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

Ваш вопрос касается не столько публикации-подписки, сколько обычной обработки сообщений.Основная проблема заключается в том, можете ли вы гарантировать, что операция будет выполнена ровно один раз.Короткий ответ заключается в том, что вы, вероятно, хотите использовать прямой обмен таким образом, чтобы сообщение помещалось в одну очередь и обрабатывалось одним (или, возможно, многими) потребителями.

Длинный ответ заключается в том, что «ровно один раз» нельзягарантированно, поэтому вам нужно сделать эту часть вашего дизайна.

Фон

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

Кроме того, вы должны знать о том факте, что невозможно гарантироватьдоставка «ровно один раз».Математически такая гарантия не может быть предоставлена.Вместо этого вы можете иметь одну из двух вещей (являющихся взаимоисключающими):

  • Максимум один раз доставки (0
  • Минимум один раз доставки (1 <=n) </li>

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

Использование подтверждений гарантирует доставку как минимум один раз.Без подтверждений возможна потеря сообщения во время операций публикации и потребления, и гарантируется только самое большее однократная доставка.

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

Последствия проектирования

Учитывая вышесказанное, важно, чтобы ваш дизайн полагался "хотя бы один раз"" Доставка.Для операции удаления это включает переписывание определения этой операции, чтобы оно было скорее утвердительным, чем процедурным (например, «Удалить this » становится «Убедитесь, что this не существует»).Разница в том, что вы описываете конечное состояние, а не процесс.

0 голосов
/ 09 декабря 2018

Мне кажется, у вас должна быть отдельная очередь для каждой службы, и этот экземпляр должен быть уведомлен об удалении записи в БД.Обменник помещает копию сообщения во все очереди.Экземпляры службы конкурируют за доступ к выделенной очереди (сообщение получает только один).

...