MSMQ + WCF - немедленно перемещайте сообщения в очередь недоставленных сообщений
У нас есть служба WCF, которая прослушивает сообщения в очереди (MSMQ). Он отправляет запрос на наш веб-сервер (REST API), который возвращает код состояния HTTP.
Если код состояния попадает в диапазон 400, мы выбрасываем сообщение. Идея состоит в том, что ошибка 400 диапазона никогда не может быть успешной (неавторизованный, неверный запрос, не найден и т. Д.), Поэтому мы не хотим продолжать повторную попытку.
Для всех других ошибок (например, 500 - Внутренняя ошибка сервера) мы настроили WCF, чтобы поместить сообщение в очередь "повторных попыток". Сообщения в очереди повторных попыток повторяются через определенное время. Идея заключается в том, что сервер временно не работает, поэтому подождите и попробуйте снова.
Способ WCF, если мы бросим FaultException
в контракте на обслуживание он автоматически помещает сообщение в очередь повторных попыток.
Когда сообщение вызывает ошибку 400 диапазона, мы просто проглатываем ошибку (мы просто регистрируем ее). Это предотвращает запуск механизма повтора; однако было бы лучше переместить сообщение в очередь недоставленных сообщений. Таким образом, мы можем отреагировать на ошибку, отправив электронное письмо пользователю и / или системному администратору.
Есть ли способ немедленно переместить эти плохие сообщения в очередь недоставленных сообщений?
2 ответа
Сначала я продолжал ссылаться на очередь недоставленных писем. В то время, когда я публиковал этот вопрос, я не знал, что WCF/MSMQ автоматически создает так называемую ядовитую подпоследовательность. Любое сообщение, которое не может быть доставлено в течение заданного количества раз, помещается в подпоследовательную очередь.
В моей ситуации я знал, что некоторые сообщения никогда не будут успешными, поэтому я хотел немедленно переместить сообщение из очереди.
Решением было создать вторую очередь, которую я назвал "ядом" (не путать с подпоследовательностью ядов). Мой блок catch мог бы создать экземпляр клиента WCF и переслать сообщение в эту очередь с ошибками. Я мог бы повторно использовать один и тот же клиент для отправки как в исходную, так и в исходную очередь; Мне просто нужно было создать отдельную конечную точку клиента в файле конфигурации для каждого.
У меня было два отдельных ServiceHost
запущенные экземпляры, которые читают очереди. ServiceHost
для исходной очереди выполнялся HTTP-запрос и перенаправлялись сообщения в очередь-ядро при возникновении неисправимых ошибок. Второй ServiceHost
будет просто отправить электронное письмо, чтобы записать, что сообщение было потеряно.
Также возникла проблема с временными ошибками, превышающими максимальное количество попыток. WCF/MSMQ автоматически создает подпоследовательность <myqueuename>;poison
, Вы не можете напрямую писать в подпоследовательность через WCF, но вы можете читать из нее, используя ServiceHost
, Всякий раз, когда сообщения попадают в подозрительную подпоследовательность, я просто пересылаю сообщение в опасную очередь с тем же клиентом, который использую в блоке перехвата исходного обработчика.
Я хотел иметь возможность включить трассировку стека в сообщения об ошибках. Поскольку я повторно использовал один и тот же клиентский и сервисный контракт для всех обработчиков, я не мог просто передать трассировку стека в виде строки (если я не добавил ее ко всем моим контрактам на данные). Вместо этого у меня был обработчик ядов, пытающийся выполнить код еще раз, который снова потерпит неудачу и выльется в стек.
Вот как выглядели мои очереди сообщений:
MyQueue
- Queue messages
- Retry
- Poison
MyQueuePoison
- Queue messages
Этот подход довольно запутанный. Странно было вызывать клиента WCF из обработчика службы WCF. Это также означало создание еще одной очереди на сервере и тонны дополнительных разделов конфигурации для указания, в какую очередь клиент должен пересылать сообщения.
Надеюсь, я понял ваш вопрос, и если это то, что я думаю, вы говорите, то да, но есть, но вам, очевидно, нужно запрограммировать его, чтобы сделать это. Но вам НЕОБХОДИМО установить количество повторных попыток, чтобы MSMQ мог повторять попытки, пока он не сдастся. Или вы можете создать свою собственную очередь для мертвых писем / сообщений
http://msdn.microsoft.com/en-us/library/ms789035(v=vs.110).aspx http://msdn.microsoft.com/en-us/library/ms752268(v=vs.110).aspx
посмотрите здесь также:
http://www.michaelfcollins3.me/blog/2012/09/20/wcf-msmq-bad-message-handling.html
Как мне обработать ошибку сообщения в привязках MSMQ для WCF
Я надеюсь, что эти ссылки помогут.