Идемпотентность сообщения - порядок заказа - PullRequest
0 голосов
/ 05 октября 2018

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

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

Вот вопросы:

  • Как мы можем сделать нашу обработку сообщений идемпотентной?
  • Если мы сохраняем каждое событие в хранилище событий,Есть ли какие-либо соображения, которые необходимо учитывать при разработке полезной нагрузки каждого события и агрегации событий для получения агрегатного состояния?

Пример : скажем, у нас есть «Пользователь»Созданные и удаленные пользователем сообщения (или любая другая пара событий, которые ДОЛЖНЫ обрабатываться по порядку).Если мы обработаем «Пользователь удален» до «Пользователь создан», пользователь не будет удален.Даже если они идут в порядке очереди в очереди.Может ли действительно идемпотентная обработка / идемпотентные события давать удаленному пользователю?

Другой пример .Давайте предположим, что у нас есть объект с атрибутом score.Пользователь может изменить счет.Вторая служба использует события службы «объект оценки», и если счет достигает 100, объект (или ссылка на объект) вставляется второй службой в объект «Лучшая категория».Если оценка достигает -20, вторая служба добавляет объект оценки в «Худшую категорию».Наличие множественного набора второй службы может дать непредсказуемый результат, если события «100 баллов» и «20 баллов» находятся в крошечном интервале времени.Любые идеи о том, как спроектировать события «Score x» или как их обработать?

Большое спасибо за вашу помощь!

1 Ответ

0 голосов
/ 08 октября 2018

Как мы можем сделать нашу обработку сообщений идемпотентной?

Вам следует:

  • игнорировать сообщения, которые вы уже "видели";это означает, что потребитель должен иметь способ обнаружить это;например, он может хранить список идентификаторов сообщений, которые он обработал (это означает, что каждое сообщение должно иметь уникальный идентификатор).
  • не выдает исключение, если сообщение не изменяет состояние;например, если вы получаете второе событие DeleteUser (таким образом, пользователь уже удален, второе удаление не должно иметь побочных эффектов), тогда вы игнорируете его.Не каждое событие может быть идемпотентным, например, UpdateUserName не должно быть идемпотентным.

Если мы сохраняем каждое событие в хранилище событий, следует ли учитывать, когдаразработка полезной нагрузки каждого события и агрегации событий для получения агрегатного состояния?

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

Пример: допустим, у нас есть сообщения «Пользователь создан» и «Пользователь удален» (или любая другая пара событий, которые НУЖНО обрабатывать по порядку).Если мы обработаем «Пользователь удален» до «Пользователь создан», пользователь не будет удален.Даже если они идут в порядке очереди в очереди.Может ли действительно идемпотентная обработка / идемпотентные события давать удаленному пользователю?

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

Это решение очень зависит от домена.

Другой пример.Давайте предположим, что у нас есть объект с атрибутом Score.Пользователь может изменить счет.Вторая служба использует события службы «объект оценки», и если счет достигает 100, объект (или ссылка на объект) вставляется второй службой в объект «Лучшая категория».Если оценка достигает -20, вторая служба добавляет объект оценки в «Худшую категорию».Наличие множественного набора второй службы может дать непредсказуемый результат, если события «100 баллов» и «20 баллов» находятся в крошечном интервале времени.Любые идеи о том, как проектировать события «Score x» или как обрабатывать эти события?

Эту ситуацию можно решить, сохранив in-the / attach-to readmodels (две коллекции, * 1039).* и worse) отметка времени / порядок / поток-версия / независимо от последнего обработанного события и игнорирует каждое событие, которое меньше или равно этой отметке времени.Таким образом, если «оценка 100» выбрасывается после «оценки -20», но прибывает первой, следует игнорировать «оценку -20», потому что она имеет более низкую отметку времени, хотя она идет последней.

Это решение является общим, но оно основано на существовании некоторого порядка.

...