События домена и управление версиями без CQRS

Привет, у меня есть следующий вариант, с которым я не понимаю, как добиться согласованности с ним:

  1. Пользователь 1 использует пользовательский интерфейс на основе задач для изменения имени клиента
  2. Служба приложений вызывает операцию в совокупности
  3. Событие срабатывания агрегата для имени клиента изменено
  4. шина отправляет сообщение, используя nservicebus
  5. Сервис NServicebus умирает
  6. Пользователь 2 получает агрегат и звонки меняют адрес
  7. Агрегатная операция называется
  8. Событие домена запущено
  9. Сообщение отправлено в автобус
  10. Автобус перезапускается
  11. Сообщение 2 получено первым
  12. Сообщение 2 обработано, и другой ограниченный контекст обновлен новым адресом
  13. Сообщение 1 получено сейчас в неправильном порядке
  14. Что происходит сейчас

В 13 будет ли ошибка оптимистичного параллелизма, если мы передадим версию агрегата в событии?

Если это так, сообщение 1 новое применяется к объекту в другом контексте. Как нам даже поддерживать последовательность?

Это проблема, которая не позволяет мне применять события в моем домене. Любая помощь приветствуется.

Основная идея - обновить другой агрегат в другом контексте. Я просто зациклился на технических аспектах параллелизма.

Мы не используем источник событий или CQRS в смысле обработчика команд и передачи команд по шине. Мы хотим, чтобы асинхронно происходила только обработка событий, поскольку у нас есть существующий дизайн, который мы не хотим изменять.

Блэр




Ответы (4)


Обычно вы ставите сообщения в очередь. Если они собираются в очередь, вы получите правильный заказ. Если вы хотите использовать что-то, что не поддерживает заказ с вашей служебной шиной, добавьте порядковый номер к своим событиям, чтобы другая сторона могла правильно их изменить. TCP делает это с 1981 года. http://www.ietf.org/rfc/rfc793.txt :)

person Greg Young    schedule 02.03.2013
comment
Я не совсем понимаю, что вы имеете ввиду. Я отправляю событие через nservicebus, поэтому нет заказа. Если я добавлю порядковый номер к своим событиям, как мне сделать заказ на другом конце? Что мне не хватает, должно быть что-то очевидное, чего я не вижу. - person Blair Davidson; 02.03.2013
comment
Также с NServicebus с несколькими потоками нет гарантии, что они будут обрабатываться по порядку. - person Blair Davidson; 02.03.2013
comment
Следите за порядковым номером на другом конце. Не обрабатывайте сообщение, пока порядковый номер не совпадет с last processed sequence number + 1. - person Martijn van den Broek; 02.03.2013
comment
nservicebus, безусловно, может писать в очередь (я считаю, что по умолчанию используется msmq). Если вы пишете в очередь, ваш заказ будет в точке записи, для нескольких потоков это может быть обработано с помощью мелкозернистой блокировки на агрегате (или в базе данных, если вы используете оптимистичный параллелизм в качестве примера) - person Greg Young; 02.03.2013
comment
для изменения порядка вы должны просто указать им порядковый номер. Event0, Event1, Event2, Event3 ... с другой стороны, если вы выйдете из строя, вы ждете. - person Greg Young; 02.03.2013
comment
Что вы подразумеваете под мелкозернистой блокировкой агрегированного или оптимистичного параллелизма? - person Blair Davidson; 02.03.2013
comment
Что вы используете для генерации чисел вроде 1,2,3, это услуга, которую использует клиент? Или в совокупности? - person Blair Davidson; 02.03.2013
comment
Нужно ли это хранить в базе данных, я имею в виду числа, чтобы сохранять их между перезапусками приложения? - person Blair Davidson; 02.03.2013
comment
Я тоже не хочу использовать поиск событий - person Blair Davidson; 02.03.2013
comment
Самый простой способ добиться этого с помощью NSB - это небольшая сага на принимающей стороне, которая отслеживает последнее обработанное событие. Но при выборе структуры данных важно также подумать о количестве сообщений, которые вы ожидаете увидеть. - person JimmyP; 04.03.2013

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

Как всегда, на ум приходит пара вопросов / проблем:

Во-первых, в вашем примере не требуется, чтобы конечная точка выходила из строя, поскольку 2 пользователя могут обновлять адрес одновременно, а порядок обработки может быть случайным. Таким образом, возникает вопрос, какой адрес является правильным. Поэтому для решения этого требуется немного больше анализа. С одной стороны, я думаю, мы могли бы предположить, что клиент не будет перемещаться так часто, чтобы 2 пользователя обновляли адрес одновременно (или даже рядом с ним) --- :)

Даже в этом случае, возможно, первый адрес правильный.

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

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

Для простого решения я бы выбрал дату отправки сообщения, соответствующую дате последней операции для определенного типа. Таким образом, для ChangeAddressCommand при обработке сообщения вы можете сравнить его с текущим LastAddressChange, и если сообщение было отправлено до даты последнего изменения, отклоните его.

person Eben Roux    schedule 02.03.2013

Аналогичная проблема с NServiceBus обсуждается здесь. OP предлагает использовать IBus.HandleCurrentMessageLater () для вращения до прибытия другого сообщения. Это может сработать, но может быть проблематичным, поскольку вы никогда не знаете, сколько времени вам придется ждать.

Более сложным вариантом было бы использование саги, которая будет ждать, пока не появятся все сообщения, ведущие к определенной версии. В этом случае упорядочение выполняется на основе версии и возможно только в том случае, если все изменения в агрегированной версии публикуются в другом BC. Предположим, что Сообщение 1 работает с версией 2 агрегата. Затем он увеличивает версию агрегата и публикует событие, указывающее, что оно работало с версией 2. Сообщение 2 работает с версией 3 агрегата и публикует событие, указывающее, что оно работало с версией 3. Когда конечная точка NServiceBus в другом BC получает Сообщение 2 перед Сообщением 1, он знает, что последнее полученное сообщение работало с версией 1 агрегата, поэтому ему нужно сообщение, которое работало с версией 2. Он запустит сагу, которая ожидает следующего сообщения. Как только он получит Сообщение 1, сага применит Сообщение 1, а затем Сообщение 2 и освободит состояние саги. Если использование версии для секвенирования неприемлемо, можно использовать другую стратегию секвенирования.

person eulerfx    schedule 02.03.2013

Согласно этому вы должны спросить себя:

Как повлияет на бизнес неудача?

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

person inf3rno    schedule 24.05.2014