2016-09-05 10 views
2

У меня есть случай синхронизации в моем дизайне CQRS/ES. Ради обсуждения давайте опишем его на примере Microsoft на эту тему, конференционное управление (https://msdn.microsoft.com/en-us/library/jj554200.aspx).CQRS/Event Sourcing/Event bus/Timing

Два контекста: управление конференцией и управление заказами. При управлении конференцией вы создаете конференцию и меняете ее свойства (например, максимальные места). Управление конференцией связывается с управлением заказами через шину событий. Таким образом, управление заказами знает, когда создается новая конференция, и создайте экземпляр объекта отслеживания (доступность места) в его контексте. Событие, такое как «максимальная доступность сидений уменьшается от 100 до 80», также сообщается из conf mgmt для заказа mgmt через автобус событий.

  • Предположим, что на минуту создана конференция (максимум 20 мест).
  • В минуту 4 событие достигает порядка mgmt заказа, и, следовательно, создается доступность места.
  • В минуту 7 пользователь сделал заказ (через управление заказами), купив все 20 мест. (это должно быть сообщено также из - управления заказами для управления conf, чтобы conf admin мог принять правильное решение).
  • В минуту 8 conf admin сделал замену на наличие мест (в контексте conf mgmt), уменьшив его до 15.
  • Уведомление от заказа mgmt (о том, что все 20 мест были проданы) прибывает с минуты 9.
  • Что теперь делать? (в conf mgmt? вы не должны были уменьшать места до 15, когда вы уже получили платеж за 20, но на минуту 8 администратор не знал об этом).

Это первый случай.

Теперь второй случай:

  • Допустим на минуту 1 конференции создается (максимум мест 20).
  • В минуту 4 событие достигает порядка mgmt заказа, и, следовательно, создается доступность места.
  • В минуту 6 conf admin сделал изменение доступности мест (в контексте conf mgmt), уменьшив его до 15.
  • В минуту 7 пользователь сделал заказ (через управление заказами), купив все 20 мест. Он не знает, что доступность сокращена до 15, потому что событие не достигло этого момента.
  • В 10 минут, наконец, прибыло уведомление от conf mgmt.
  • Что теперь делать?

Эти проблемы связаны с техническими проблемами (задержка при передаче события). Есть ли чисто технические способы избежать этого? Если нет, то каким будет бизнес-путь/дизайн-способ преодолеть это?

Добавлено примечание: Я знаю, что это проблема возможной согласованности, относящаяся к архитектуре CQRS/ES. В одном контексте это может быть легче решить, потому что для этого вы можете использовать команды (например, отменить). Но между ограниченным контекстом вы не должны передавать команды, вы общаетесь только с событиями, и я думаю, что событие не является правильной абстракцией для этого (потому что оно представляет собой то, что произошло). Или я чего-то не хватает?

Добавлено примечание: может быть, эта статья может предоставить больше контекста и намекнуть на решение, хотя для этого конкретного случая в этом вопросе я так не думаю (речь идет не о сообщении не по порядку). http://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-i-of-ii/

Добавлено примечание: или, может быть, ... в контексте управления заказами мы можем просто поставить очередь на команду для покупки места, пока мы не узнаем, что мы получили последнее/последнее событие из контекста управления конференцией. Я имею в виду, события приходят с меткой времени, не так ли? Таким образом, мы можем сравнить временную метку последнего события, которое мы получили от conf mgmt, с отметкой времени для команды покупки места. Если ts последнего события меньше, чем ts команды, мы просто не выполняем выполнение команды, пока не получим событие, ts которого больше ts команды. Такого рода ответственность несет менеджер процесса (сага).

Будет ли это работать? Это правильный подход?

Добавлено примечание: соответствующая тема>Implementing a Saga/Process Manager in a CQRS http application. Я думаю, что мы на правильном пути с менеджером процессов. Как сказал ответчик: «Вы просто не отвечаете« Подтвержденный заказ »сразу. Посмотрите, как это делают Amazon и другие торговые сайты: после получения заказа вы получаете только подтверждение« Принятое заказ »(например, HTTP Code 202 Accepted). ".

Это до логики технолога-менеджер, чтобы решить, когда на самом деле выполнить команду (на основе определенного состояния, внутреннее состояние, может быть, или в этом случае последнее получило событие от другого контекста).

Любые мнения?

Спасибо, Raka

+0

В описываемом вами сценарии, что говорит бизнес? Спросите эксперта по домену, что должно произойти в этом сценарии – tomliversidge

ответ

3

Три possi Задолженность

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

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

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

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

Это предполагает, что управление конференцией должно поддерживать инвариант, что количество зарезервированных мест меньше, чем количество выделенных. На самом деле это не может быть правдой в вашем бизнесе. Кроме того, может быть полезно, чтобы бизнес мог отслеживать количество попыток клиента зарезервировать больше мест, чем было доступно.

В-третьих, возможно, что ваши границы обслуживания нарисованы в неправильном месте. Udi Dahan wrote

Любая часть данных или правило должны принадлежать только одной службе.

Если места в управлении конференцией и места в управлении заказами - одно и то же, то, возможно, они принадлежат друг другу (та же граница обслуживания).

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

2

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

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

в вас Например, если кто-то разместил заказ на 20 мест, но они были впоследствии сокращен до 15 лет, вы можете:

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

Они в непосредственной близости от верхней части моей головы ...

Важно спросить бизнес. Они часто вас удивят!

Если этот ответ вернется, его никогда не должно произойти, тогда в другом ответе есть некоторые разумные предложения по этому вопросу.

2

Позволяет начать с того, что я вижу как самую большую проблему в вашем дизайне: ваш агрегат требует много времени для обновления.

Отличный способ разработки вашего продукта: GUI -> API -> Command -> CommandHandler [Сообщать, что агрегат что-то может быть обновлен] -> Событие [Сначала переходит к агрегату, а затем к другим подписчикам] , Вы также должны убедиться, что события применяются до того, как будет обработана новая команда. Поэтому ваш CommandHandler должен завершить команду Command перед тем, как начать с новой. Теперь, учитывая, сколько команд, которые вы ожидаете обрабатывать для любой единицы времени, вам придется впоследствии моделировать. Но если вы сделаете это, вы убедитесь, что Aggregate может принять соответствующее решение, если команда является действительной или нет.

Почему я считаю это большой проблемой? Потому что, если у вас есть команда, которая хочет забронировать все места, вы хотите быть уверены, что есть много доступных мест. Вы делаете не хотите, чтобы событие отставало, что уменьшило количество доступных мест.Агрегат должен всегда иметь реальную информацию. В противном случае вы создадите недействительные события, которые являются большими, нет-нет.

Все это порождает вопрос: «Где должна быть бизнес-логика?» Ну, это может быть несколько сложно. Агрегат является единственным (или должен быть единственным), который знает, в каком состоянии он находится. Но CommandHandler также должен проверить, является ли команда действительной. Таким образом, ваша логика может стать разделенной между агрегатом и commandHandler. Простой способ сделать split состоит в том, что CommandHandler должен только проверять, является ли это допустимой командой, в то время как Aggregate должен проверить «могу ли я действительно сделать это?».

Таким образом, если мы представим себе вышеупомянутый раскол, и мы имеем ваш сценарий 1.

  1. CreateConferenceCommand ("MyConference", 20 мест)
  2. ConferenceCommandHandler (команда CreateConferenceCommand)
    • Проверьте, если команда содержит всю необходимую информацию
    • Сообщите агрегированную команду, и она попросила обновить информацию.
  3. Совокупный ОК с изменениями.
    • В этом случае агрегат был создан и имеет 20 мест.
  4. ConferenceUpdatedEvent создан и опубликован.
  5. OrderCommand («MyConference», 20 мест)
    • Что это на самом деле означает, что (если оно было подтверждено, и все, что) до вас.
  6. ConferenceCommandHandler (OrderCommand ввод команда)
    • Проверьте команду содержит весь необходимый INFO
    • Сообщите агрегировать команду прибыла и попросила, чтобы обновить с информацией.
  7. Совокупный ОК с изменениями.
    • У этого было 20 мест, поэтому он в порядке.
  8. ConferenceUpdatedEvent создан и опубликован
    • "MyConference" уменьшает количество доступных мест с 20.
  9. ChangeSeatsCommand ("MyConference", 15 мест)
  10. (команда ChangeSeatsCommand)
  11. ConferenceCommandHandler
    • Проверьте, содержит ли команда всю необходимую информацию.
    • Сообщите агрегированную команду и попросили обновить ее с помощью информации.
  12. Aggreget не OK изменения.
    • Поскольку все места были забронированы, и мы предполагаем, что за них заплатили, мы не можем просто изменить количество мест. Поэтому мы блокируем изменение.
  13. Сообщите об ошибке.

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

Я надеюсь, что это несколько поможет вам.

+0

wow спасибо за парней-парней, дай мне пару дней, чтобы пережевать их и вернуться к нему. –