#architecture #rabbitmq #microservices #devops #eventual-consistency
Вопрос:
Мы настроили наш микросервис на использование rabbitmq
очередей для обработки любых предстоящих данных.
Итак, у нас есть service A
, service B
, service C
и service D
.
Когда приходит запрос на создание пользователя service A
, он создает пользователя и помещает событие в newUserIsCreated
очередь.
Теперь service B
и service C
необходимо обновить свою базу данных для вновь добавленного пользователя.
Проблема:
Что делать, если создание пользователя завершится неудачно в любом service B
и service C
.
Возможными сценариями сбоя могут быть сбой проверки или сбой service B
service C
и.
Существует также проблема при service D
попытке доступа к одному и тому же пользователю.
Чем бы service B
и service C
ответили? Потому что к тому времени у них не будет вновь созданного пользователя.
Подводить итоги,
Как справиться с ошибкой проверки или любым другим сбоем между этими службами?
Что делать, если требуется синхронизация в реальном времени? (обработка очередей может занять некоторое время)
Комментарии:
1. Я думаю, что в вашем случае использования вместо rabbitmq у вас должен быть другой
service-x
, который вызывает три другие службы, если кто-либо из служб отключен или не отвечает, выservice-x
должны иметь возможность выполнять операции отката.
Ответ №1:
Вы могли бы B
и C
(и любая другая служба, которая должна подтвердить, что пользователь создан) опубликовать сообщение с подтверждением в RabbitMQ, которое будет принято A
; A
затем не подтверждает, что пользователь был создан, пока он не получит подтверждения. Это не является надежным: есть все шансы, что он везде преуспел, но A
не получил подтверждения вовремя. Для этой (в идеале редкой) ситуации у вас может быть процесс очистки.
Однако стоит отметить, что такого рода синхронные отношения в основном переопределяют запрос/ответ через очередь сообщений, поэтому, если идти по этому пути, почему бы просто не выполнить прямой запрос/ответ (например, HTTP или gRPC)?
Если у вас есть операция, которая должна повлиять на несколько служб, часто бывает полезно смоделировать ее как сагу, которая будет отправлять запросы различным службам и обрабатывать сбои (и, возможно, откажется, если было слишком много сбоев, откатив внесенные изменения). Сохранив состояние саги (например , обновлено B
, но C
еще не подтверждено обновление), ее можно запросить.
Если вы обнаружите , что большинство операций в B
являются частью приложения sagas A
, то, возможно, стоит подумать о том, должна ли B
и A
должна ли быть одна и та же услуга, которая обеспечит более строгие гарантии согласованности, а также, вероятно, упростит работу.
Комментарии:
1. Это надежный ответ. Я бы добавил, что для несколько похожего приложения, в котором периодические отключения были фактом жизни, мы создали микросервис «ConsistencyAudit» (отдельно), который подписывался на
...created
события из нескольких служб и следил за любыми пропусками, а затем предпринял некоторые действия, чтобы уведомить администратора. Простой, отдельный, производительный и (как оказалось) ненужный, но был создан для аналогичных задач.2. Да, в более ориентированной на события системе я бы выбрал именно это.