MSMQ + WCF - немедленно перемещать сообщения в очередь недоставленных сообщений

У нас есть служба WCF, которая прослушивает сообщения в очереди (MSMQ). Он отправляет запрос на наш веб-сервер (REST API), который возвращает код состояния HTTP.

Если код состояния попадает в диапазон 400, мы отбрасываем сообщение. Идея состоит в том, что ошибка диапазона 400 никогда не может быть успешной (несанкционированный, неверный запрос, не найден и т. Д.), И поэтому мы не хотим повторять попытки.

Для всех других ошибок (например, 500 - Internal Server Error) у нас настроен WCF для помещения сообщения в очередь «повторных попыток». Сообщения в очереди повторных попыток повторяются через определенное время. Идея в том, что сервер временно не работает, поэтому подождите и попробуйте еще раз.

Способ настройки WCF: если мы добавим FaultException в контракт службы, он автоматически поместит сообщение в очередь повторных попыток.

Когда сообщение вызывает ошибку диапазона 400, мы просто проглатываем ошибку (мы просто регистрируем ее). Это предотвращает срабатывание механизма повтора; однако было бы лучше переместить сообщение в очередь недоставленных сообщений. Таким образом, мы можем отреагировать на ошибку, отправив электронное письмо пользователю и / или системному администратору.

Есть ли способ немедленно переместить эти плохие сообщения в очередь недоставленных сообщений?


person Travis Parks    schedule 30.05.2014    source источник
comment
Я знаю, что вы хотите использовать WCF, но то, о чем вы просите, можно легко сделать, если вы просто воспользуетесь классом MessageQueue. В MSMQ есть многое, что WCF не позволяет вам использовать. msdn.microsoft.com/en-us/library/   -  person MickyD    schedule 07.06.2014


Ответы (2)


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

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

Решением было создать вторую очередь, которую я назвал «отравой» (не путать с подочередью с отравлением). Мой блок catch создает экземпляр клиента WCF и пересылает сообщение в эту подозрительную очередь. Я мог бы повторно использовать один и тот же клиент для отправки сообщений как в исходную, так и в подозрительную очередь; Мне просто нужно было создать отдельную конечную точку клиента в файле конфигурации для каждого.

У меня было два отдельных ServiceHost экземпляра, которые читали очереди. ServiceHost для исходной очереди выполнял HTTP-запрос и перенаправлял сообщения в подозрительную очередь при возникновении неисправимых ошибок. Второй ServiceHost просто отправит электронное письмо, чтобы записать, что сообщение было потеряно.

Также была проблема временных ошибок, превышающих максимальное количество попыток. WCF / MSMQ автоматически создает вложенную очередь с именем <myqueuename>;poison. Вы не можете напрямую писать в под-очередь через WCF, но вы можете читать из нее, используя ServiceHost. Всякий раз, когда сообщения попадают в подозрительную под-очередь, я просто пересылаю сообщение в опасную очередь с тем же самым клиентом, который я использую в блоке catch исходного обработчика.

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

Вот как выглядели мои очереди сообщений:

MyQueue
    - Queue messages
    - Retry
    - Poison
MyQueuePoison
    - Queue messages

Этот подход довольно запутанный. Было странно вызывать клиент WCF из обработчика службы WCF. Это также означало создание еще одной очереди на сервере и тонны дополнительных разделов конфигурации для указания, в какую очередь клиент должен пересылать сообщения.

person Travis Parks    schedule 11.03.2015

Надеюсь, я понял ваш вопрос, и если, как мне кажется, вы это говорите, то да, есть, но вам, очевидно, нужно запрограммировать его для этого. Но вам НЕОБХОДИМО установить количество повторов, чтобы 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

Надеюсь, эти ссылки помогут.

person Ahmed ilyas    schedule 30.05.2014
comment
Таким образом, обычно сообщение повторяется только определенное количество раз, основанное на свойстве MaxRetryCycles. Но в моем случае повторять попытку нет смысла. Я хочу немедленно перейти в очередь недоставленных писем. - person Travis Parks; 30.05.2014
comment
Мне было интересно, пришлось ли мне вручную создавать еще одну конечную точку для очереди недоставленных сообщений, создавать другой контракт на обслуживание и создавать другого клиента и явно вызывать его в коде обработки 400. Похоже, что просто перейти непосредственно в очередь недоставленных сообщений - это много. - person Travis Parks; 30.05.2014
comment
да, я не думаю, что вы можете перейти непосредственно к очереди недоставленных писем. Может быть, вам стоит установить максимальное количество повторных попыток равным 1 - какой вред от повторной попытки? он потерпел неудачу в первый раз, поэтому он может потерпеть неудачу во второй раз или может быть успешным (что хорошо) - person Ahmed ilyas; 30.05.2014
comment
@Ahmedilyas Если вы установите максимальное количество повторных попыток равным 1, это повлияет на все сообщения, даже те, которые могут потерпеть неудачу один раз, но с учетом шанса могут быть успешными в следующий раз. Повторная попытка 1 не только предотвращает 400 запросов, но и серьезно ограничивает полноту использования MSMQ. - person MickyD; 07.06.2014
comment
@MickyDuncan - спасибо. У меня создалось впечатление, что при повторной попытке сообщения будут отправлены повторно, если они не будут доставлены - просто. - person Ahmed ilyas; 07.06.2014
comment
@Ahmedilyas да, но в данном случае только один раз. По большому счету, повторная попытка 1 обычно бесполезна. См. JMS; ApacheMQ; Образцы ОВОС для примеров - person MickyD; 07.06.2014