Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Отравляющее сообщение — это сообщение, превышающее максимальное количество попыток доставки приложению. Эта ситуация может возникнуть, когда приложение на основе очередей не может обработать сообщение из-за ошибок. Для удовлетворения требований надежности приложение, в очереди, получает сообщения в рамках транзакции. Прерывание транзакции, в которой было получено сообщение в очереди, оставляет сообщение в очереди, чтобы его можно было повторно обработать в новой транзакции. Если проблема, вызвавшая прерывание транзакции, не исправляется, принимающее приложение может застрять в цикле, получая и отменяя одно и то же сообщение до тех пор, пока не будет превышено максимальное количество попыток доставки и не возникнет ядовитое сообщение.
Сообщение может стать ядным сообщением по многим причинам. Наиболее распространенные причины связаны с конкретными приложениями. Например, если приложение считывает сообщение из очереди и выполняет некоторую обработку базы данных, приложение может не получить блокировку базы данных, что приведет к прерыванию транзакции. Так как транзакция базы данных была прервана, сообщение остается в очереди, что приводит к повторному прочтению сообщения во второй раз и попытке получить блокировку базы данных. Сообщения также могут стать подозрительными, если они содержат недопустимые сведения. Например, заказ на покупку может содержать недопустимый номер клиента. В таких случаях приложение может добровольно прервать транзакцию и заставить сообщение стать подозрительным сообщением.
В редких случаях сообщения могут не отправляться в приложение. Слой Windows Communication Foundation (WCF) может найти проблему с сообщением, например, если сообщение имеет неправильный кадр, недопустимые учетные данные сообщения, подключенные к нему, или недопустимый заголовок действия. В таких случаях приложение никогда не получает сообщение; однако сообщение по-прежнему может стать подозрительным сообщением и обрабатываться вручную.
Обработка подозрительных сообщений
В WCF обработка отравляющих сообщений обеспечивает механизм для приложения для работы с сообщениями, которые не могут быть переданы в приложение, или с сообщениями, которые отправлены в приложение, но не могут быть обработаны по специфическим причинам, связанным с приложением. Настройте обработку подозрительных сообщений со следующими свойствами в каждой из доступных привязок очереди:
ReceiveRetryCount. Целочисленное значение, указывающее максимальное число попыток доставки сообщения из очереди приложения в приложение. Значение по умолчанию — 5. Это достаточно в случаях, когда немедленная повторная попытка устранить проблему исправляет её, например, при временном зависании в базе данных.MaxRetryCycles. Целочисленное значение, указывающее максимальное число циклов повторных попыток. Цикл повторных попыток состоит из передачи сообщения из очереди приложения в подочередь повторных попыток, а затем, после настраиваемой задержки, из подочереди повторных попыток обратно в очередь приложения для повторной доставки. Значение по умолчанию: 2. В Windows Vista сообщение выполняется не более (ReceiveRetryCount+1) * (MaxRetryCycles+ 1) раз.MaxRetryCyclesне обрабатывается в Windows Server 2003 и Windows XP.RetryCycleDelay. Задержка времени между циклами повторных попыток. Значение по умолчанию составляет 30 минут.MaxRetryCyclesиRetryCycleDelayвместе предоставляют механизм для решения задачи, когда повторная попытка после периодической задержки устраняет проблему. Например, это обрабатывает заблокированный набор строк в транзакции SQL Server, ожидающей подтверждения.ReceiveErrorHandling. Перечисление, указывающее действие, выполняемое для сообщения, которое завершилось сбоем доставки после максимального количества попыток повтора. Значения могут быть "Сбой", "Пропустить", "Отклонить" и "Переместить". Параметр по умолчанию — "Ошибка".Вина. Этот параметр отправляет сбой прослушивателю, который привел к сбою
ServiceHost. Сообщение должно быть удалено из очереди приложения каким-либо внешним механизмом, прежде чем приложение сможет продолжать обрабатывать сообщения из очереди.Капля. Этот параметр удаляет отравляющее сообщение, и сообщение никогда не доставляется приложению. Если на этом этапе срок действия свойства
TimeToLiveсообщения истек, то сообщение может появиться в очереди недоставленных писем отправителя. Если нет, сообщение не отображается нигде. Этот параметр указывает, что пользователь не указал, что делать, если сообщение потеряно.Откажитесь. Этот параметр доступен только в Windows Vista. Это указывает очереди сообщений (MSMQ) отправить негативное подтверждение обратно диспетчеру очереди отправителя о том, что приложение не может получить сообщение. Сообщение помещается в очередь недоставленных писем диспетчера очередей.
Переместить. Этот параметр доступен только в Windows Vista. Это перемещает отравляющее сообщение в очередь отравляющих сообщений для последующей обработки с помощью приложения обработки сообщений с отравляемым сообщением. Очередь необработанных сообщений — это подочередь очереди приложения. Приложение для обработки ядовитых сообщений может быть службой WCF, которая считывает сообщения из очереди ядовитых сообщений. Очередь яда является подочередью очереди приложения и может быть обращена как net.msmq://<имя-компьютера>/applicationQueue;poison, где имя-компьютера — это имя компьютера, на котором находится очередь, а applicationQueue — это имя очереди, специфичной для приложения.
Ниже приведено максимальное количество попыток доставки для сообщения:
((ReceiveRetryCount+1) * (MaxRetryCycles+1)) в Windows Vista.
(ReceiveRetryCount + 1) в Windows Server 2003 и Windows XP.
Примечание.
Повторные попытки не выполняются для сообщения, доставленного успешно.
Чтобы отслеживать количество попыток чтения сообщения, Windows Vista поддерживает свойство долговечности сообщения, которое подсчитывает количество прерываний, и свойство счетчика перемещения, которое подсчитывает количество перемещений сообщения между очередью приложения и подочередями. Канал WCF использует их для вычисления количества попыток повторного получения и количества циклов повторных попыток. В Windows Server 2003 и Windows XP счетчик прерываний сохраняется в памяти каналом WCF и при сбое приложения сбрасывается. Кроме того, канал WCF может содержать число прерываний до 256 сообщений в памяти в любой момент времени. Если читается 257-е сообщение, то счетчик прерываний для самого старого сообщения сбрасывается.
Свойства счетчика прерываний и перемещения доступны для операции службы через контекст операции. В следующем примере кода показано, как получить к ним доступ.
MsmqMessageProperty mqProp = OperationContext.Current.IncomingMessageProperties[MsmqMessageProperty.Name] as MsmqMessageProperty;
Console.WriteLine($"Abort count: {mqProp.AbortCount} ");
Console.WriteLine($"Move count: {mqProp.MoveCount} ");
// code to submit purchase order ...
WCF предоставляет две стандартные привязки с очередями:
NetMsmqBinding. Привязка .NET Framework, подходящая для выполнения взаимодействия на основе очередей с другими конечными точками WCF.
MsmqIntegrationBinding. Привязка, подходящая для взаимодействия с существующими приложениями очереди сообщений.
Примечание.
Вы можете изменить свойства в этих привязках на основе требований службы WCF. Весь механизм обработки подозрительных сообщений является локальным для принимающего приложения. Процесс невидим для отправляющего приложения, если принимающее приложение в конечном итоге не останавливается и не отправляет отрицательное подтверждение отправителю. В этом случае сообщение перемещается в очередь недоставленных писем отправителя.
Лучшая практика: Обработка MsmqPoisonMessageException
Когда служба определяет, что сообщение является ядовитым, очередь транспорта выдает MsmqPoisonMessageException, содержащий LookupId ядовитого сообщения.
Принимающее IErrorHandler приложение может реализовать интерфейс для обработки любых ошибок, необходимых приложению. Дополнительные сведения см. в Расширение управления обработкой и отчетностью об ошибках.
Приложению может потребоваться автоматическая обработка подозрительных сообщений, которая перемещает подозрительные сообщения в очередь подозрительных сообщений, чтобы служба может получить доступ к остальным сообщениям в очереди. Единственный сценарий использования механизма обработчика ошибок для обработки исключений от подозрительных сообщений заключается в том, когда параметр ReceiveErrorHandling установлен на Fault. В примере с ядовитым сообщением для Message Queuing 3.0 демонстрируется это поведение. Ниже описаны действия по обработке подозрительных сообщений, включая рекомендации.
Убедитесь, что настройки соответствуют требованиям вашего приложения. При работе с параметрами убедитесь, что вы понимаете различия между возможностями очереди сообщений в Windows Vista, Windows Server 2003 и Windows XP.
При необходимости реализуйте
IErrorHandlerдля обработки ошибок отравленных сообщений. Поскольку для установкиReceiveErrorHandlingнаFaultтребуется ручной механизм перемещения проблемного сообщения из очереди или исправление внешней зависимости, типичное использование заключается в реализацииIErrorHandler, еслиReceiveErrorHandlingустановлено наFault, как показано в следующем коде.class PoisonErrorHandler : IErrorHandler { public void ProvideFault(Exception error, MessageVersion version, ref Message fault) { // No-op -We are not interested in this. This is only useful if you want to send back a fault on the wire…not applicable for queues [one-way]. } public bool HandleError(Exception error) { if (error != null && error.GetType() == typeof(MsmqPoisonMessageException)) { Console.WriteLine($" Poisoned message -message look up id = {((MsmqPoisonMessageException)error).MessageLookupId}"); return true; } return false; } }Создайте
PoisonBehaviorAttribute, который может использовать поведение сервиса. Поведение устанавливаетIErrorHandlerна диспетчер. См. следующий пример кода.public class PoisonErrorBehaviorAttribute : Attribute, IServiceBehavior { Type errorHandlerType; public PoisonErrorBehaviorAttribute(Type errorHandlerType) { this.errorHandlerType = errorHandlerType; } void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase) { } void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters) { } void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase) { IErrorHandler errorHandler; try { errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType); } catch (MissingMethodException e) { throw new ArgumentException("The errorHandlerType specified in the PoisonErrorBehaviorAttribute constructor must have a public empty constructor", e); } catch (InvalidCastException e) { throw new ArgumentException("The errorHandlerType specified in the PoisonErrorBehaviorAttribute constructor must implement System.ServiceModel.Dispatcher.IErrorHandler", e); } foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers) { ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher; channelDispatcher.ErrorHandlers.Add(errorHandler); } } }Убедитесь, что служба помечена атрибутом поведения яда.
Кроме того, если для ReceiveErrorHandling задано значение Fault, то ServiceHost выдает ошибку при обнаружении ошибочного сообщения. Вы можете подключиться к неисправному событию и завершить работу службы, выполнить корректирующие действия и перезапустить. Например, LookupId в MsmqPoisonMessageException распространяемом IErrorHandler сообщении можно отметить и при сбоях узла службы, можно использовать System.Messaging API для получения сообщения из очереди, используя LookupId его для удаления сообщения из очереди и хранения сообщения в каком-либо внешнем хранилище или другой очереди. Затем можно перезапустить ServiceHost, чтобы возобновить обычную обработку. Обработка проблемных сообщений в MSMQ 4.0 демонстрирует это поведение.
Транзакции Time-Out и отравленные сообщения
Класс ошибок может возникать между каналом транспорта в очереди и пользовательским кодом. Эти ошибки могут быть обнаружены слоями между уровнями, такими как уровень безопасности сообщений или логика отправки служб. Например, случай с отсутствующим сертификатом X.509, обнаруженным на уровне безопасности SOAP, и случай с отсутствующим действием являются примерами того, когда сообщение передаётся в приложение. В этом случае модель службы удаляет сообщение. Поскольку сообщение считывается в рамках транзакции, и результат этой транзакции не может быть предоставлен, транзакция в конечном итоге истекает, прерывается, и сообщение помещается обратно в очередь. Другими словами, для определенного класса ошибок транзакция не сразу прерывается, но ожидает, пока транзакция не истекает. Вы можете изменить время ожидания транзакции для службы с помощью #B0.
Чтобы изменить время ожидания транзакции на уровне компьютера, измените файл machine.config и задайте соответствующее время ожидания транзакции. Важно отметить, что в зависимости от времени ожидания, заданного в транзакции, транзакция в конечном итоге прерывается и возвращается в очередь, а его количество прерываний увеличивается. В конечном итоге сообщение становится опасным, и осуществляется правильная обработка в соответствии с параметрами пользователя.
Сеансы и токсичные сообщения
Процедуры повтора и обработки "ядовитых" сообщений для сеанса такие же, как для отдельного сообщения. Свойства, ранее перечисленные для подозрительных сообщений, применяются ко всему сеансу. Это означает, что попытка выполнения всего сеанса повторяется и он отправляется в окончательную очередь ядовитых сообщений или очередь недоставленных сообщений отправителя, если сообщение отклонено.
Пакетная обработка и подозрительные сообщения
Если сообщение становится подозрительным и является частью пакета, то весь пакет откатывается, а канал возвращается к чтению одного сообщения одновременно. Для получения дополнительной информации о пакетной обработке см. раздел Пакетные сообщения в транзакции.
Обработка ядовитых сообщений для сообщений в ядовитой очереди
Обработка сообщений-ядов не заканчивается после того, как сообщение помещено в очередь ядовитых сообщений. Сообщения в очереди подозрительных сообщений по-прежнему должны быть прочитаны и обработаны. Вы можете использовать подмножество параметров обработки ядовитых сообщений при чтении сообщений из конечной очереди ядовитых сообщений. Применимые параметры: ReceiveRetryCount и ReceiveErrorHandling. Вы можете задать для ReceiveErrorHandling значение Drop, Отклонить или Ошибка.
MaxRetryCycles игнорируется, и исключение возникает, если ReceiveErrorHandling задано значение Move.
Различия Windows Vista, Windows Server 2003 и Windows XP
Как отмечалось ранее, к Windows Server 2003 и Windows XP применяются не все параметры обработки сообщений с подозрительными сообщениями. Следующие ключевые различия между очередью сообщений в Windows Server 2003, Windows XP и Windows Vista относятся к обработке подозрительных сообщений:
Очередь сообщений в Windows Vista поддерживает вложенные запросы, а Windows Server 2003 и Windows XP не поддерживают вложенные запросы. Вложенные запросы используются в обработке подозрительных сообщений. Очереди повторных попыток и очередь сбойных сообщений являются вложенными очередями в очереди приложения, созданной на основе настроек обработки сбойных сообщений. Определяет
MaxRetryCycles, сколько повторных попыток необходимо создать. Поэтому при запуске на Windows Server 2003 или Windows XPMaxRetryCyclesигнорируются, аReceiveErrorHandling.Moveне разрешается.Очередь сообщений в Windows Vista поддерживает отрицательное подтверждение, а Windows Server 2003 и Windows XP его не поддерживают. Отрицательное подтверждение от принимающего диспетчера очередей приводит к тому, что диспетчер очереди отправки помещает отклоненное сообщение в очередь недоставленных писем. Таким образом,
ReceiveErrorHandling.Rejectне разрешено использовать с Windows Server 2003 и Windows XP.Очередь сообщений в Windows Vista поддерживает свойство сообщения, которое сохраняет количество попыток доставки сообщений. Это свойство счётчика прерываний недоступно в Windows Server 2003 и Windows XP. WCF сохраняет количество прерываний в памяти, поэтому это свойство может не содержать точного значения, если одно сообщение считывается несколькими службами WCF в ферме.