Статьи

MSMQ, WCF и IIS: как заставить их играть хорошо — Часть 3

Ранее в MSMQ, WCF и IIS: чтобы они хорошо играли:

  • В первой части мы создали клиентское приложение и приложение-службу IIS и установили связь между ними через MSMQ с помощью WCM NetMsmqBinding.
  • Во второй части мы развернули одно и то же приложение на нескольких серверах и включили безопасность транспорта для MSMQ.

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

Идут Транзакционные

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

  1. Сообщения будут доставлены ровно один раз и по порядку.
  2. Сообщения сохраняются на диске, поэтому они не будут потеряны, если сервер выйдет из строя.
  3. Отправка и получение сообщений могут происходить в рамках транзакции. Я нашел это наиболее полезным для принимающей стороны: если вы создаете одну транзакцию, которая включает в себя как получение сообщения, так и его обработку, и во время обработки происходит сбой, вся транзакция будет откатываться. Это означает, что сообщение будет возвращено в очередь, а не потеряно.

В это время вы, вероятно, думаете: «Ух ты, все звучит замечательно — почему никто не хочет всех этих?» Основной причиной является производительность — использование транзакционных очередей сообщений обычно во много раз медленнее, чем с их нетранзакционными кузенами. Кроме того, хотя перспектива потери сообщений или получения дубликатов сообщений кажется пугающей, в действительности это может произойти только при крайне редких и неудачных обстоятельствах. Поэтому вопрос здесь должен быть не «хотите ли вы повысить надежность, которую вы получаете из очередей транзакционных сообщений», а скорее «можете ли вы позволить себе жить без него?».

Тем не менее, существует множество сценариев, в которых очереди транзакционных сообщений оправданы, например, хранение записей аудита, обработка финансовых транзакций или отправка приветствий в примерах блога. Итак, начнем!

Создать транзакционную очередь сообщений

Первое, что нам нужно сделать, это создать новую блестящую очередь транзакционных сообщений. Даже если у нас уже есть нетранзакционная очередь сообщений с правильным именем, вы не можете преобразовать нетранзакционную очередь в транзакционную. Таким образом, вам нужно будет бесцеремонно удалить существующую очередь и создать новую личную очередь, которая по-прежнему называется MsmqService / MsmqService.svc . Однако на этот раз убедитесь, что вы установили флажок Transactional .

Теперь, после всех наших усилий по настройке списков ACL в предыдущей очереди, убедитесь, что вы правильно установили их в новой очереди, чтобы избежать более болезненных проблем с разрешениями!

Переконфигурируйте привязки WCF

Еще раз, нам нужно изменить конфигурацию WCF как в клиенте, так и в службе, чтобы использовать новую привязку. На этот раз мы будем использовать MsmqBindingTransactionalTransportSecurity , который будет определен следующим образом:

<binding name="MsmqBindingTransactionalTransportSecurity" exactlyOnce="true" receiveErrorHandling="Move">
<security mode="Transport"/>
</binding>

ExactlyOnce = «истина» атрибут WCF -говорить для использования транзакционной очереди сообщений. receiveErrorHandlingАтрибут необходим только на стороне службы (хотя он не причинит никакого вреда на стороне клиента). Это говорит WCF, что делать в случае, если он обнаруживает «ядовитое сообщение». Ядовитые сообщения — важная концепция с транзакционными очередями сообщений. Как обсуждалось ранее, если при обработке транзакционного сообщения возникает ошибка, транзакция будет откатываться и сообщение будет возвращено обратно в свою очередь — готово для повторного получения той же службой. Если ошибка была вызвана временным сбоем, сообщение может быть успешно обработано в следующий раз. Однако, если проблема возникла из-за неверно сформированного сообщения или постоянной проблемы с приложением, сообщение будет повторяться снова и снова. WCF и MSMQ 4.0 объединили свои усилия для обеспечения поддержки обнаружения и обработки ядовитых сообщений.Если одно и то же сообщение не удается несколько раз (по умолчанию 3), оно будет считаться «ядом». Что будет дальше, зависит от значенияатрибут receiveErrorHandling . Если вы установите для него значение «Переместить» (мой любимый выбор!), Оно будет автоматически помещено в подпоследовательность под названием «яд», где он может быть обработан вручную кем-то другим.

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

Добавьте атрибуты транзакции к вашей реализации сервиса

Если мы хотим воспользоваться преимуществами выполнения приема и обработки сообщений в одной транзакции, вам нужно указать .NET включить ваш код в существующую транзакцию MSMQ. Это можно сделать в одной строке кода, декорировав методы реализации службы с помощью [OperationBehavior (TransactionScopeRequired = true)].

До сих пор мой пример службы состоял из одной строки кода. Хотя простота, как правило, хорошая вещь в примерах, она не даст мне никакой возможности проверить поведение транзакций или обработку ядовитых сообщений. Чтобы сделать сценарий немного более интересным, я добавил код, который позволит мне легко создать вредоносное сообщение. Мой класс обслуживания теперь выглядит так:

public class MsmqService : IMsmqContract
{
[OperationBehavior(TransactionScopeRequired=true)]
public void SendMessage(string message)
{
if (message == "Bad")
{
throw new InvalidOperationException("Bad!");
}

Trace.WriteLine(String.Format("Received message at {0} : {1}", DateTime.Now, message));
}
}

Как я уверен, вы можете сказать, что всякий раз, когда я отправляю сообщение «Плохо», мой сервис не работает. Это приведет к возникновению исключения, и транзакция будет прервана. В результате сообщение будет возвращено обратно в очередь сообщений, готово для повторного получения. Поскольку сообщение не было изменено, оно продолжит сбоить еще два раза, после чего WCF решит, что сообщение является вредоносным, и переместит его в подпоследовательность «яд».

Проверьте настройку DTC

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

  1. Убедитесь, что служба DTC установлена ​​и работает на всех серверах. Если вы используете Windows Server 2008, эта функция может быть не установлена ​​по умолчанию.
  2. Проверьте настройки безопасности DTC. В Windows Vista запустите comexp.msc, затем разверните Службы компонентов \ Компьютеры \ Мой компьютер \ Контроллер распределенных транзакций \ Локальный код неисправности. В Windows Server 2008 это немного легче найти в диспетчере серверов. В обоих случаях щелкните правой кнопкой мыши локальный код неисправности, выберите «Свойства» и перейдите на вкладку «Безопасность». Точный выбор параметров, вероятно, зависит от вашего сценария, но хорошим началом является включение «Доступ по DTC по сети», «Разрешить удаленные клиенты», «Разрешить входящие», «Разрешить исходящие» и «Аутентификация не требуется».
  3. Убедитесь, что вы разрешаете трафик DTC через любые брандмауэры. Опять же, если вы столкнетесь с проблемами, хорошей отправной точкой будет временное отключение всех брандмауэров, чтобы вы могли выяснить, является ли это источником ваших проблем.

Вывод

В последних трех постах я довольно хорошо описал все, что я узнал за последние несколько месяцев о том, как MSMQ, WCF и IIS 7 могут играть хорошо, как на одной, так и на нескольких машинах. Несмотря на то, что потребовалось много времени, чтобы понять все это, я все же считаю, что архитектура чрезвычайно гибкая и простая в использовании — общий объем кода в этом решении действительно крошечный. Моя единственная реальная жалоба в том, что в инструментах или в Интернете не так много помощи, чтобы объяснить, почему вещи не всегда работают с первого раза или как их исправить. В этом посте я надеюсь, что опыт моей команды сделает ваш путь немного более гладким для вас.

Вы можете скачать исходный код готового проекта с этого места .