2015-09-14 4 views
1

У нас есть требование для обработки всех наших сообщений в порядке поступления в MSMQ.Nservicebus Sequence

Мы будем предоставлять услуги WCF клиентам, и эта служба WCF отправит сообщения с помощью NServiceBus (Sendonly Bus) в MSMQ.

Мы планируем создать службу Windows (MessageHandler), которая будет использовать Nservicebus для чтения сообщения из MSMQ и сохранения его в базе данных. Наша база данных будет недоступна в течение нескольких часов каждый день.

Во время простоя db мы ожидаем, что процесс повторит первое сообщение в MSMQ и прекратит обработку других сообщений до тех пор, пока база данных не будет готова. После того, как база данных будет готова, мы хотим, чтобы NServicebus обрабатывал в том порядке, в котором отправлено сообщение.

Будет ли настраиваться MaximumConcurrencyLevel = "1" MaximumMessageThroughputPerSecond = "1" помогает в этом сценарии?

Каков наилучший способ использования NServiceBus для обработки этого сценария?

ответ

1

У нас есть требование ко всем нашим сообщениям, которые должны быть обработаны в приходе прибытия в MSMQ в .

Смотрите ответ на этот вопрос How to handle message order in nservicebus?, а также этот пост here.

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

  • Добавить порядковый номер для всех сообщений
  • в приемнике проверьте порядковый номер последний видел номер + 1, если не бросить аут исключения последовательности
  • Включить повторные попытки второго уровня (так что, если они вышли из строя, они попытаются еще раз позже, надеюсь, после того, как правильно было получено сообщение)

Однако в межд erest от конечной точки и нажмите ваш конкретный вопрос:

Будет ли настройка MaximumConcurrencyLevel = "1" MaximumMessageThroughputPerSecond = "1" помогает в этом случае?

Не совсем.

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

Где это происходит до вас (проверить resequencer pattern), но вы могли бы, конечно, задушить обработчик NserviceBus к одной теме (я не думаю, что вам нужно установить MaximumMessageThroughputPerSecond, чтобы сделать его однопоточный, хотя).

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

Во время простоя дб мы ожидаем, что этот процесс, чтобы повторить первое сообщение MSMQ и остановить не обрабатывать другие сообщения до базы вверх. После того, как база данных будет готова, мы хотим, чтобы NServicebus обрабатывал в заказе сообщение, отправленное.

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

Для начала, когда конечная точка обработчика сообщения NServiceBus пытается обработать сообщение в очереди ввода и обнаруживает, что база данных недоступна, она реализует политику повторного повторения второго уровня, которая по умолчанию будет пытаться выполнить сброс 5 раз с увеличением нечастота, а затем терпеть неудачу навсегда, приклеив сообщение об ошибке в очереди ошибок. Затем он переместится на следующее сообщение во входной очереди.

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

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

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

Однако менеджер службы Windows, не поддерживает концепцию обслуживания окон, поэтому вам придется использовать запланированное задание, чтобы остановить затем запустить службу, или посмотреть на другие варианты, такие как hangfire, quartz.net или какой-либо другой cron-type библиотеки.

+0

Большое спасибо. Это было действительно полезно. – Mike

1

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

Следует просто признать, что могут быть сообщения OrderLine без Order. В любом случае, Order придет позже. Возможная последовательность.

Другой - собирать сообщения (и возможное состояние) в саге NServiceBus. Когда обычно MessageA должен прибыть первым, только чтобы получить MessageB и MessageC позже, дайте всем трем сообщениям возможность начать сагу. Все три сообщения должны иметь что-то, что связывает их вместе, как уникальный GUID. Тогда сага будет следить за тем, чтобы они собирали их должным образом и когда все сообщения прибыли, возможно, сохраняют свое окончательное состояние и отмечают сагу как завершенную.

Другой вариант - просто сохранить все сообщения непосредственно в базе данных и что-то еще выяснить, что к чему.Это сценарий, полезный для хранилища данных, где данные необходимо собирать, независимо от того, что. Некоторые данные могут быть не на 100% точными (или непротиворечивыми), но все в порядке.

Асинхронный обмен сообщениями затрудняет их обработку на 100% по порядку, особенно когда клиент, вызывающий WCF, совершает ошибки и/или отправляет их из строя. Это было бы не в первый раз, когда у меня было такое требование и сообщения из-за порядка.