Нужна ли мне служебная шина для простой асинхронной обработки команд?
-
12-12-2019 - |
Вопрос
Моя система использует шаблон команды с отдельными обработчиками.Мои команды выполняются в CommandService, который в настоящее время обрабатывает все команды в процессе.
У меня есть определенные команды, которые выполняют хотя бы одну из этих операций, которые являются медленными операциями:
- Отправляет электронное письмо
- Создает PDF-файл
- Отправляет факс
- Взаимодействует со сторонними веб-сервисами
Я хочу, чтобы все эти команды обрабатывались вне процесса, чтобы пользовательский интерфейс был более быстрым.
Должен ли я использовать шину обмена сообщениями только для этих команд или мне следует вызвать внутрипроцессный обработчик команд? BeginInvoke()
?
Изменить – дополнительная информация
В системе небольшое количество пользователей (возможно, 100 одновременно в напряженный день), поэтому очередь, скорее всего, никогда не станет очень длинной.Главное здесь — сократить время блокировки пользовательского интерфейса при отправке электронного письма с вложенным PDF-файлом (рассматриваемая команда).Сотрудникам приходится выполнять эту команду много раз в день.
Принимая во внимание всю ситуацию, я думаю, что я собираюсь пойти с BeginInvoke()
на данный момент по нескольким причинам:
- Необходимо будет коснуться всех взаимодействий пользовательского интерфейса, чтобы убедиться, что они ведут себя так, как будто команда выполнена успешно.Напоминание о том, что «вам необходимо отправить этот документ», находится в нескольких местах пользовательского интерфейса, и после отправки отчета оно полностью обновляет страницу.
- Сейчас середина напряженного сезона у моих клиентов (более 50% годового бизнеса они выполняют летом), поэтому мне не кажется разумным в настоящее время вводить совершенно новую часть инфраструктуры, с администрированием которой я не знаком. .
Но зная то, что я знаю сейчас, в новой системе я бы с самого начала использовал служебную шину для любых медленных команд (практически каждая система должна отправлять электронную почту) и спроектировал пользовательский интерфейс так, чтобы команды можно было легче переключать с синхронного режима. к асинхронной обработке.В реализации это по сути означает, что каждый POST является AJAX и выполняет действие в пользовательском интерфейсе, как если бы оно было успешным.(Для примера посмотрите, как Facebook обрабатывает комментарии.)
Решение
Оба решения имеют свои плюсы и минусы.
- BeginInvoke — чрезвычайно простое решение, и его семантика такая же, как прямой вызов обработчика по команде.Но это решение зависит от инфраструктуры потоков:максимальное количество потоков, замороженный поток из-за одновременного доступа к ресурсам ввода-вывода и т. д.
- MessageBus — очень гибкое и мощное решение, позволяющее контролировать каждый аспект процесса обработки команд.Но это вводит в ваше приложение еще один уровень абстракции, что было бы излишней инженерией в том случае, если чем проще, тем лучше.
Я бы рекомендовал оценить требования к загрузке вашей системы, количество этих фоновых задач, коэффициент роста и т. д. и в зависимости от этого принять решение.
Но, по моему личному мнению, внедрение автобусного решения подходит в 80% случаев.Вы можете представить простую реализацию шины, которую при необходимости можно будет расширить на следующих итерациях.
Другие советы
Вероятно, это скорее вопрос надежности, который подтолкнет вас к шине сообщений.Видите ли, если ваша исходная транзакция (та, которая выполнила BeginInvoke) прошла успешно, а затем в середине вашего вызова произошел сбой сервера, у вашей системы не было бы памяти, которая ей все еще нужна для отправки электронного письма или создания PDF-файла. .
Шина сообщений сможет откатить эту вторую транзакцию в очередь, чтобы при повторном запуске сервера он снова отправлял электронное письмо.