MVC - WCF - RabbitMQ - Событие домена через очередь сообщений для ускорения потребителя или альтернативы?
Управляемый доменом дизайн Передача событий в отдельные контексты
Пользовательское действие в MVC должно генерировать событие, которое передается удаленному (той же локальной сети) обработчику события.
Что я проверял:
- MVC: вызов службы запускается и забывается (асинхронный) ->
- (Размещенный IIS) WCF, который собирает данные и заполняет сообщение ->
- Отправлено через EasyNetQ/RabbitMQ ServiceBus ->
- Событие используется подписчиком (используя контейнер DI, инициализированный из конечной точки службы WCF), который обрабатывает событие и его данные.
Я провел некоторое тестирование, чтобы увидеть, как это работает, если сервис вызывается довольно быстро, зацикливаясь на стороне MVC
for (int i = 0; i < 200; i++)
{
...
client.MyServiceMethod(someId, startDate);
...
}
Часть MessageQueue является быстрой, основываясь на временных метках, которые она отправляет в очередь и получает подписчиком в течение той же секунды. Цикл вызовов службы WCF очень медленный. Проходит много секунд, чтобы пройти через них. Я попытался переключиться с wsHttpBinding на netTcpBinding и поиграть с сервисом Throtttling в WCF.
WCF не является обязательным, но кажется, что отдельный проект по обработке событий (на стороне издателя) был бы полезен и мог бы быть физически расположен в другом месте приложения MVC (снижение нагрузки и т. Д.). Является ли WCF правдоподобным для подобной ситуации, или я должен попытаться использовать службы Windows или другие автономные приложения, например консольное приложение и т. Д., Или, возможно, использовать поток в MVC для генерации данных о событиях, или существуют лучшие сценарии? Каковы лучшие практики в этом типе системы обработки событий? По сути, кажется, что было бы полезно иметь что-то, генерирующее данные о событии, поскольку оно должно быть обработано где-то, не замедляя пользовательский интерфейс, который использует конечный пользователь.
2 ответа
Если я хорошо понял, ваш процесс создания событий "тяжелый", и вы хотите избежать создания в процессе MVC. Я полагаю, вы отправляете некоторую информацию в службу WCF, чтобы позволить ему подготовить мероприятие.
Можно подумать о сценарии с двумя потребителями, избегающем шаг WCF:
- Ваше приложение MVC создает и публикует "легкое" событие со всеми данными, необходимыми для создания "тяжелого" события (в основном с входными данными, которые вы передаете в WCF)
EventCreator
подписчик потребляет это сообщение и готовит тяжелое событие- Ваш уже существующий потребитель будет затем поглощать тяжелое событие
EasyNetQ уже предоставляет простые функции для публикации и использования сообщения. Большинство учебных пособий, которые вы найдете в Интернете, предлагают использовать TopShelf для размещения ваших потребителей в консольном приложении (отладка) или в службе Windows (производство). У EasyNetQ есть пример здесь: EasyNetQ с TopShelf
Если вы хотите "скрыть" зависимость EasyNetQ от вашего проекта MVC, вы можете обернуть EasyNetQ IBus
на заказ Bus
и использовать контейнер IoC для внедрения конкретной реализации вашей шины. В приведенном выше примере используется Castle.Windsor
как контейнер IoC
Вместо того, чтобы пытаться развернуть свою собственную инфраструктуру, как это, я думаю, что вам лучше использовать такой инструмент, как NServiceBus (не бесплатный) или MassTransit (бесплатный). (Я хотел бы рассмотреть эту лучшую практику.)
Я не могу говорить за MassTransit, но мой опыт работы с NServiceBus был очень хорошим. Вам нужно только указать, какие сообщения попадают в какую очередь. Вы можете использовать несколько разных технологий организации очередей, но я бы порекомендовал начать с реализации MSMQ по умолчанию. Не нужно никаких кошмаров по настройке WCF.;)
Все ваши обработчики сообщений также будут автоматически упакованы в распределенную транзакцию, поэтому в случае сбоя взаимодействия с БД все сообщение будет откатано, и вы сможете попробовать сообщение еще раз в будущем.